// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core;
///
/// 堆栈扩展方法
///
public static class StackExtensions
{
///
/// 批量入栈
///
/// 堆栈元素类型
/// 堆栈实例
/// 要入栈的元素集合
/// 堆栈或元素集合为空时抛出
public static void PushRange(this Stack stack, IEnumerable items)
{
ArgumentNullException.ThrowIfNull(stack);
ArgumentNullException.ThrowIfNull(items);
foreach (var item in items)
{
stack.Push(item);
}
}
///
/// 批量入栈(保持集合的原始顺序)
///
/// 堆栈元素类型
/// 堆栈实例
/// 要入栈的元素集合
/// 堆栈或元素集合为空时抛出
public static void PushRangeReversed(this Stack stack, IEnumerable items)
{
ArgumentNullException.ThrowIfNull(stack);
ArgumentNullException.ThrowIfNull(items);
// 反转顺序入栈,使得弹出时保持原始顺序
var itemsArray = items.ToArray();
for (var i = itemsArray.Length - 1; i >= 0; i--)
{
stack.Push(itemsArray[i]);
}
}
///
/// 批量出栈
///
/// 堆栈元素类型
/// 堆栈实例
/// 要出栈的元素数量
/// 出栈的元素集合
/// 堆栈为空时抛出
/// 数量小于0或大于堆栈长度时抛出
public static IEnumerable PopRange(this Stack stack, int count)
{
ArgumentNullException.ThrowIfNull(stack);
if (count < 0)
{
throw new ArgumentOutOfRangeException(nameof(count), "数量不能小于0");
}
if (count > stack.Count)
{
throw new ArgumentOutOfRangeException(nameof(count), "数量不能大于堆栈长度");
}
var result = new List(count);
for (var i = 0; i < count; i++)
{
result.Add(stack.Pop());
}
return result;
}
///
/// 尝试出栈多个元素
///
/// 堆栈元素类型
/// 堆栈实例
/// 要出栈的元素数量
/// 出栈的元素集合
/// 是否成功出栈指定数量的元素
public static bool TryPopRange(this Stack stack, int count, out IEnumerable items)
{
items = [];
if (count < 0 || count > stack.Count)
{
return false;
}
var result = new List(count);
var tempItems = new List();
for (var i = 0; i < count; i++)
{
if (stack.TryPop(out var item))
{
result.Add(item);
tempItems.Add(item);
}
else
{
// 恢复已出栈的元素
for (var j = tempItems.Count - 1; j >= 0; j--)
{
stack.Push(tempItems[j]);
}
return false;
}
}
items = result;
return true;
}
///
/// 清空堆栈并返回所有元素
///
/// 堆栈元素类型
/// 堆栈实例
/// 堆栈中的所有元素
/// 堆栈为空时抛出
public static IEnumerable DrainToList(this Stack stack)
{
ArgumentNullException.ThrowIfNull(stack);
var result = new List(stack.Count);
while (stack.Count > 0)
{
result.Add(stack.Pop());
}
return result;
}
///
/// 安全地查看堆栈顶部元素
///
/// 堆栈元素类型
/// 堆栈实例
/// 堆栈顶部元素
/// 是否成功查看
public static bool TryPeek(this Stack stack, out T? item)
{
item = default;
if (stack.Count == 0)
{
return false;
}
item = stack.Peek();
return true;
}
///
/// 安全地查看多个顶部元素(不出栈)
///
/// 堆栈元素类型
/// 堆栈实例
/// 要查看的元素数量
/// 顶部指定数量的元素
/// 堆栈为空时抛出
/// 数量小于0或大于堆栈长度时抛出
public static IEnumerable PeekRange(this Stack stack, int count)
{
ArgumentNullException.ThrowIfNull(stack);
if (count < 0)
{
throw new ArgumentOutOfRangeException(nameof(count), "数量不能小于0");
}
if (count > stack.Count)
{
throw new ArgumentOutOfRangeException(nameof(count), "数量不能大于堆栈长度");
}
var items = stack.ToArray();
return items.Take(count);
}
///
/// 检查堆栈是否为空
///
/// 堆栈元素类型
/// 堆栈实例
/// 堆栈是否为空
public static bool IsEmpty(this Stack stack)
{
return stack?.Count == 0;
}
///
/// 检查堆栈是否不为空
///
/// 堆栈元素类型
/// 堆栈实例
/// 堆栈是否不为空
public static bool IsNotEmpty(this Stack stack)
{
return stack?.Count > 0;
}
///
/// 将堆栈转换为数组,保持堆栈顺序
///
/// 堆栈元素类型
/// 堆栈实例
/// 包含堆栈所有元素的数组
/// 堆栈为空时抛出
public static T[] ToArrayPreserveOrder(this Stack stack)
{
ArgumentNullException.ThrowIfNull(stack);
return [.. stack];
}
///
/// 复制堆栈
///
/// 堆栈元素类型
/// 原堆栈
/// 复制的新堆栈
/// 堆栈为空时抛出
public static Stack Clone(this Stack stack)
{
ArgumentNullException.ThrowIfNull(stack);
// 保持原始堆栈的顺序
var items = stack.ToArray();
return new Stack(items);
}
///
/// 查找堆栈中是否包含满足条件的元素
///
/// 堆栈元素类型
/// 堆栈实例
/// 匹配条件
/// 是否包含满足条件的元素
/// 堆栈或条件为空时抛出
public static bool Contains(this Stack stack, Func predicate)
{
ArgumentNullException.ThrowIfNull(stack);
ArgumentNullException.ThrowIfNull(predicate);
return stack.Any(predicate);
}
///
/// 统计堆栈中满足条件的元素数量
///
/// 堆栈元素类型
/// 堆栈实例
/// 匹配条件
/// 满足条件的元素数量
/// 堆栈或条件为空时抛出
public static int Count(this Stack stack, Func predicate)
{
ArgumentNullException.ThrowIfNull(stack);
ArgumentNullException.ThrowIfNull(predicate);
return stack.Count(predicate);
}
///
/// 对堆栈中的每个元素执行指定操作(从顶部到底部)
///
/// 堆栈元素类型
/// 堆栈实例
/// 要执行的操作
/// 堆栈或操作为空时抛出
public static void ForEach(this Stack stack, Action action)
{
ArgumentNullException.ThrowIfNull(stack);
ArgumentNullException.ThrowIfNull(action);
foreach (var item in stack)
{
action(item);
}
}
///
/// 对堆栈中的每个元素执行指定操作(带索引,从顶部到底部)
///
/// 堆栈元素类型
/// 堆栈实例
/// 要执行的操作,参数为元素和索引
/// 堆栈或操作为空时抛出
public static void ForEach(this Stack stack, Action action)
{
ArgumentNullException.ThrowIfNull(stack);
ArgumentNullException.ThrowIfNull(action);
var index = 0;
foreach (var item in stack)
{
action(item, index++);
}
}
///
/// 创建一个新堆栈,包含满足条件的元素
///
/// 堆栈元素类型
/// 原堆栈
/// 筛选条件
/// 包含满足条件元素的新堆栈
/// 堆栈或条件为空时抛出
public static Stack Where(this Stack stack, Func predicate)
{
ArgumentNullException.ThrowIfNull(stack);
ArgumentNullException.ThrowIfNull(predicate);
var filteredItems = stack.Where(predicate).ToArray();
return new Stack(filteredItems);
}
///
/// 创建一个新堆栈,包含转换后的元素
///
/// 原堆栈元素类型
/// 目标堆栈元素类型
/// 原堆栈
/// 转换函数
/// 包含转换后元素的新堆栈
/// 堆栈或转换函数为空时抛出
public static Stack Select(this Stack stack, Func selector)
{
ArgumentNullException.ThrowIfNull(stack);
ArgumentNullException.ThrowIfNull(selector);
var transformedItems = stack.Select(selector).ToArray();
return new Stack(transformedItems);
}
///
/// 反转堆栈中的元素顺序
///
/// 堆栈元素类型
/// 堆栈实例
/// 堆栈为空时抛出
public static void Reverse(this Stack stack)
{
ArgumentNullException.ThrowIfNull(stack);
if (stack.Count <= 1)
{
return;
}
var items = new T[stack.Count];
var index = 0;
while (stack.Count > 0)
{
items[index++] = stack.Pop();
}
foreach (var item in items)
{
stack.Push(item);
}
}
///
/// 获取堆栈的深度副本(递归反转以保持原始顺序)
///
/// 堆栈元素类型
/// 原堆栈
/// 深度副本的新堆栈
/// 堆栈为空时抛出
public static Stack DeepClone(this Stack stack)
{
ArgumentNullException.ThrowIfNull(stack);
var tempStack = new Stack();
var result = new Stack();
// 第一次反转到临时堆栈
foreach (var item in stack)
{
tempStack.Push(item);
}
// 第二次反转到结果堆栈,恢复原始顺序
while (tempStack.Count > 0)
{
result.Push(tempStack.Pop());
}
return result;
}
///
/// 限制堆栈的最大长度,超出时移除底部元素
///
/// 堆栈元素类型
/// 堆栈实例
/// 最大长度
/// 堆栈为空时抛出
/// 最大长度小于0时抛出
public static void LimitSize(this Stack stack, int maxSize)
{
ArgumentNullException.ThrowIfNull(stack);
if (maxSize < 0)
{
throw new ArgumentOutOfRangeException(nameof(maxSize), "最大长度不能小于0");
}
if (stack.Count <= maxSize)
{
return;
}
// 将堆栈内容转移到数组,保留最新的maxSize个元素
var items = stack.ToArray();
stack.Clear();
// 重新入栈最新的maxSize个元素
for (var i = Math.Min(maxSize - 1, items.Length - 1); i >= 0; i--)
{
stack.Push(items[i]);
}
}
///
/// 安全地入栈元素,如果堆栈已满则移除底部元素
///
/// 堆栈元素类型
/// 堆栈实例
/// 要入栈的元素
/// 堆栈最大长度
/// 被移除的元素(如果有)
/// 堆栈为空时抛出
/// 最大长度小于1时抛出
public static T? PushWithLimit(this Stack stack, T item, int maxSize)
{
ArgumentNullException.ThrowIfNull(stack);
if (maxSize < 1)
{
throw new ArgumentOutOfRangeException(nameof(maxSize), "最大长度不能小于1");
}
T? removedItem = default;
if (stack.Count >= maxSize)
{
// 将所有元素转移到数组
var items = stack.ToArray();
stack.Clear();
// 保存被移除的底部元素
if (items.Length > 0)
{
removedItem = items[items.Length - 1];
}
// 重新入栈,跳过底部元素
for (var i = Math.Min(maxSize - 2, items.Length - 2); i >= 0; i--)
{
stack.Push(items[i]);
}
}
stack.Push(item);
return removedItem;
}
///
/// 检查是否所有元素都满足条件
///
/// 堆栈元素类型
/// 堆栈实例
/// 匹配条件
/// 是否所有元素都满足条件
/// 堆栈或条件为空时抛出
public static bool All(this Stack stack, Func predicate)
{
ArgumentNullException.ThrowIfNull(stack);
ArgumentNullException.ThrowIfNull(predicate);
return stack.All(predicate);
}
///
/// 检查是否至少有一个元素满足条件
///
/// 堆栈元素类型
/// 堆栈实例
/// 匹配条件
/// 是否至少有一个元素满足条件
/// 堆栈或条件为空时抛出
public static bool Any(this Stack stack, Func predicate)
{
ArgumentNullException.ThrowIfNull(stack);
ArgumentNullException.ThrowIfNull(predicate);
return stack.Any(predicate);
}
///
/// 合并两个堆栈(第二个堆栈的元素将位于顶部)
///
/// 堆栈元素类型
/// 第一个堆栈
/// 第二个堆栈
/// 合并后的新堆栈
/// 任一堆栈为空时抛出
public static Stack Concat(this Stack first, Stack second)
{
ArgumentNullException.ThrowIfNull(first);
ArgumentNullException.ThrowIfNull(second);
var result = new Stack();
// 先添加第一个堆栈的元素(从底部到顶部)
var firstItems = first.ToArray();
for (var i = firstItems.Length - 1; i >= 0; i--)
{
result.Push(firstItems[i]);
}
// 再添加第二个堆栈的元素(从底部到顶部)
var secondItems = second.ToArray();
for (var i = secondItems.Length - 1; i >= 0; i--)
{
result.Push(secondItems[i]);
}
return result;
}
}