C#:SkipLast实现

Svi*_*ish 1 c# ienumerable implementation extension-methods

我需要一个方法来给我所有但序列中的最后一项.这是我目前的实施:

    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;
                }
        }
    }
Run Code Online (Sandbox Code Playgroud)

我需要的是对除了最后一项之外的所有项目做一些事情.在我的例子中,我有一系列具有各种属性的对象.然后我按日期订购它们,然后我需要对所有这些进行调整,除了最近的项目(这将是订购后的最后一项).

事实上,我对这些调查员和其他东西都不太了,也没有任何人在这里问过:p我想知道的是,如果这是一个很好的实现,或者我在某个地方做了一个小错误或大错.或者,如果可能这个问题是一个奇怪的,等等.

我想更通用的实现可能是一种AllExceptMaxBy方法.因为那就是它的本质.该MoreLinq有一个MaxByMinBy方法,我的方法种类需要做的是相同的,但返回的每一项除了最大或最小的一个.

Jon*_*eet 9

这很棘手,因为"最后一个元素"不是马尔可夫的停止点:你不能告诉你到最后一个元素,直到你试图获得下一个元素.这是可行的,但只有你不介意永远是"背后的一个元素".这基本上是你当前的实现,它看起来没问题,虽然我可能会略有不同.

另一种方法是使用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;
    }
}
Run Code Online (Sandbox Code Playgroud)

另一种选择,更接近您的代码:

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这样可以避免嵌套(如果序列为空则通过提前退出)并且它使用"真实"而不是条件而不是 while(true)