【发布时间】:2009-01-04 03:59:05
【问题描述】:
我在查看我的代码时发现了一些我编写的扩展方法,用于从 System.Collections.Generic.Stack 中删除项目。我很好奇,所以我查看了 Stack with Reflector 的源代码,我可以看到他们将它实现为数组而不是链表,我只是想知道为什么?使用链表就无需调整内部数组的大小...
这是我的扩展,欢迎任何批评或建议。谢谢。
public static Stack<T> Remove<T>(this Stack<T> stack, T item)
{
Stack<T> newStack = new Stack<T>();
EqualityComparer<T> eqc = EqualityComparer<T>.Default;
foreach( T newItem in stack.Reverse() )
{
if( !eqc.Equals(newItem, item) )
{
newStack.Push(newItem);
}
}
return newStack;
}
/// <summary>
/// Returns a new Stack{T} with one or more items removed, based on the given predicate.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="stack"></param>
/// <param name="fnRemove"></param>
/// <returns>The new stack.</returns>
/// <remarks>
/// We have to turn tricks in order to save the LIFO order of the pool
/// since there is no built-in remove method since they implement a Stack internally
/// as an array instead of a linked list. Maybe they have a good reason, I don't know...
///
/// So, to fix this I'm just using a LINQ extension method to enumerate in reverse.
/// </remarks>
public static Stack<T> RemoveWhere<T>(this Stack<T> stack, Predicate<T> fnRemove)
{
Stack<T> newStack = new Stack<T>();
foreach( T newItem in stack.Reverse() )
{
/// Check using the caller's method.
if( fnRemove(newItem) )
{
/// It's not allowed in the new stack.
continue;
}
newStack.Push(newItem);
}
return newStack;
}
【问题讨论】:
-
一个更有趣的问题是为什么 List 也用数组来实现。插入和删除是 O(n)。
-
nobugs: get(int) and remove(int) are O(n) is in LinkedList as well.
-
旁注:要消除
continue的使用,显然可以反转 if 语句。我没有反对继续,但你在这里不需要它。 -
@BenKnoble 谢谢!你当然是对的。在这个小例子中,它似乎不合逻辑,但总的来说,在很久以前阅读 Pragmatic Programmer 之后,我总是倾向于 early-exits 而不是 if-statements。总的来说,对我的代码的影响是更少的嵌套,更容易阅读代码和 cmets。所以这就是这里发生的事情 - 只是我的习惯。今天(在我晚年)我会少用括号。
标签: c# .net data-structures