在C#中,有没有办法将一个堆栈推送到另一个堆栈而不迭代堆栈元素?如果没有,我应该使用更好的数据结构吗?在Java中,您可以这样做:
stack1.addAll(stack2)
我希望找到C#模拟......
答案 0 :(得分:3)
<强> 0。安全解决方案 - 扩展方法
public static class Util {
public static void AddAll<T>(this Stack<T> stack1, Stack<T> stack2) {
T[] arr = new T[stack2.Count];
stack2.CopyTo(arr, 0);
for (int i = arr.Length - 1; i >= 0; i--) {
stack1.Push(arr[i]);
}
}
}
最好的方法是创建扩展方法。请注意,我将第一个堆栈放在另一个堆栈的“顶部”,可以说是从arr.Length-1循环到0.所以这段代码:
Stack<int> x = new Stack<int>();
x.Push(1);
x.Push(2);
Stack<int> y = new Stack<int>();
y.Push(3);
y.Push(4);
x.AddAll(y);
将导致x为:4,3,2,1。如果你推1,2,3,4,你会期望的是什么。当然,如果你要遍历第二个堆栈并实际弹出元素然后将它们推送到第一个堆栈,那么最终会得到1,2,4,3。再次,根据需要修改for循环。或者您可以添加另一个参数来指定您想要的行为。我没有Java方便,所以我不知道他们做了什么。
话虽如此,你可以这样做,但我不保证它会继续工作。 MS可以始终更改调用ToList时堆栈的默认行为。但是,这个更短,在我的机器上使用.NET 4.5与上面的扩展方法相同:
1 Line Linq解决方案:
y.Reverse().ToList().ForEach(item => x.Push(item));
答案 1 :(得分:2)
在你的问题中,想要这样做“不迭代堆栈元素”基本上意味着基于LinkedList
的堆栈,你只需加入第一个和最后一个元素,以便在恒定时间内组合堆栈。
但是,除非你有一个非常具体的理由使用LinkedList
,否则迭代基于数组的(List
)堆栈元素可能更好。
就具体实现而言,您应该澄清是否希望第二个堆栈以相同的堆栈顺序添加到第一个堆栈中,或者通过弹出来反转到第一个堆栈中。
答案 2 :(得分:1)
addAll
只是添加所有项目的foreach
循环的便捷方法。除此之外你真的没什么可做的:
foreach(var item in stack2)
stack1.Push(item);
如果你特别经常这样做,你可以为它自己添加一个扩展方法。
答案 3 :(得分:0)
这并不意味着使用当前的.NET Stack实现。
为了将Stack的内容“移植”到另一个堆栈的末尾而不迭代其元素内部实现细节,必须知道Stack类如何将它们存储在内存中。基于封装原理,这些信息“正式”只在Stack类本身内部知道。 .NET的Stack没有公开这样做的方法,因此如果没有使用反射,就无法像OP请求那样做。
可以想象,您可以使用反射将一个Stack的内部数组附加到另一个Stack的内容中,并且还更新存储堆栈长度的字段,但这将高度依赖于Stack类的实现,该类可以在框架的未来版本没有警告。
如果你真的需要一个可以做到这一点的Stack,你可以从头编写自己的Stack类,或者只使用另一个集合,如ArrayList
或LinkedList
,它们具有你想要的方法并添加{{1 }}和Push
扩展方法。