我需要一种方法来为我提供序列中除最后一项以外的所有项。这是我当前的实现:
public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source)
{
using (IEnumerator<T> iterator = source.GetEnumerator())
{
if(iterator.MoveNext())
while(true)
{
var current = iterator.Current;
if(!iterator.MoveNext())
yield break;
yield return current;
}
}
}
我需要它来处理除最后一项之外的所有项目。在我的例子中,我有一系列具有各种属性的对象。然后我按日期订购它们,然后我需要对除了最近的项目(这将是订购后的最后一个)之外的所有项目进行调整。
事情是,我对这些枚举器和东西还不太感兴趣,也没有人在这里问 :p 我想知道这是一个好的实现,还是我做了一个小或大的某处失误。或者如果这个问题的处理方式很奇怪,等等。
我想更通用的实现可能是 AllExceptMaxBy
方法。因为这就是它的样子。 MoreLinq有一个 MaxBy
和 MinBy
方法,我的方法有点需要做同样的事情,但返回除最大或最小项之外的所有项目。
最佳答案
这很棘手,因为“最后一个元素”不是马尔可夫停止点:在您尝试获取下一个元素之前,您无法判断您已经到达最后一个元素。这是可行的,但前提是您不介意永远成为“落后的一个元素”。这基本上就是您当前的实现所做的,它看起来还不错,尽管我可能会写得略有不同。
另一种方法是使用 foreach
,除非您处于第一次迭代,否则始终生成先前返回的值:
public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source)
{
T previous = default(T);
bool first = true;
foreach (T element in source)
{
if (!first)
{
yield return previous;
}
previous = element;
first = false;
}
}
另一种选择,更接近您的代码:
public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source)
{
using (IEnumerator<T> iterator = source.GetEnumerator())
{
if(!iterator.MoveNext())
{
yield break;
}
T previous = iterator.Current;
while (iterator.MoveNext())
{
yield return previous;
previous = iterator.Current;
}
}
}
这避免了相当深的嵌套(如果序列为空则提前退出)并且它使用“真实的”while 条件而不是 while(true)
关于C#:SkipLast 实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/969091/