C#:SkipLast实现

C#:SkipLast实现,c#,extension-methods,ienumerable,implementation,C#,Extension Methods,Ienumerable,Implementation,我需要一种方法来提供序列中除了最后一项以外的所有内容。这是我当前的实现: public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source) { using (IEnumerator<T> iterator = source.GetEnumerator()) { if(iterator.MoveNext())

我需要一种方法来提供序列中除了最后一项以外的所有内容。这是我当前的实现:

    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;
                }
        }
    }
公共静态IEnumerable SkipLast(此IEnumerable源代码)
{
使用(IEnumerator迭代器=source.GetEnumerator())
{
if(iterator.MoveNext())
while(true)
{
var current=迭代器.current;
如果(!iterator.MoveNext())
屈服断裂;
产生回流电流;
}
}
}
我需要它的目的是对除最后一项之外的所有项目进行处理。在我的例子中,我有一系列具有各种属性的对象。然后我按日期订购,然后我需要对所有商品进行调整,但最近的商品除外(这将是订购后的最后一个)

问题是,我还不太喜欢这些枚举器之类的东西,这里也没有人问:p我想知道的是,这是一个好的实现,还是我在某个地方犯了一个小错误或大错误。或者,也许这个问题是个奇怪的问题,等等


我想更一般的实现可能是
AllExceptMaxBy
方法。因为事实就是这样。有一个
MaxBy
MinBy
方法,我的方法也需要这样做,但返回除最大值或最小值之外的所有项。

您的实现在我看来非常好-这可能是我的方法

关于你的情况,我建议的唯一简化方法是将列表按相反的顺序排列(即升序而不是降序)。虽然这可能不适合您的代码,但它允许您简单地使用
collection.Skip(1)
获取除最近的项目外的所有项目


如果由于您未在帖子中显示的原因而无法实现,那么您当前的实现就没有问题。

您的实现在我看来非常好-这可能是我会采用的方式

关于你的情况,我建议的唯一简化方法是将列表按相反的顺序排列(即升序而不是降序)。虽然这可能不适合您的代码,但它允许您简单地使用
collection.Skip(1)
获取除最近的项目外的所有项目

如果由于您未在帖子中展示的原因而无法实现,那么您当前的实现根本没有问题。

这是一个棘手的问题,因为“最后一个元素”不是马尔可夫停止点:在尝试获取下一个元素之前,您无法判断您已经到达了最后一个元素。这是可行的,但前提是你不介意永远“落后一方”。这基本上就是您当前的实现所做的,它看起来还不错,尽管我可能会写一些不同的东西

另一种方法是使用
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;
    }
}
公共静态IEnumerable SkipLast(此IEnumerable源代码)
{
T先前=默认值(T);
bool first=true;
foreach(源中的T元素)
{
如果(!第一个)
{
以前的收益率;
}
先前=元素;
第一个=假;
}
}
另一个选项,更接近您的代码:

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;
        }
    }
}
公共静态IEnumerable SkipLast(此IEnumerable源代码)
{
使用(IEnumerator迭代器=source.GetEnumerator())
{
如果(!iterator.MoveNext())
{
屈服断裂;
}
T previous=迭代器.Current;
while(iterator.MoveNext())
{
以前的收益率;
previous=迭代器.Current;
}
}
}
这避免了嵌套太深(如果序列为空,则提前退出),并使用“real”while条件而不是
while(true)

这很棘手,因为“last element”不是马尔可夫停止点:在尝试获取下一个元素之前,无法判断您已经到达了最后一个元素。这是可行的,但前提是你不介意永远“落后一方”。这基本上就是您当前的实现所做的,它看起来还不错,尽管我可能会写一些不同的东西

另一种方法是使用
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;
    }
}
公共静态IEnumerable SkipLast(此IEnumerable源代码)
{
T先前=默认值(T);
bool first=true;
foreach(源中的T元素)
{
如果(!第一个)
{
以前的收益率;
}
先前=元素;
第一个=假;
}
}
另一个选项,更接近您的代码:

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;
        }
    }
}
公共静态IEnumerable SkipLast(此IEnumerable源代码)
{
使用(IEnumerator迭代器=source.GetEnumerator())
{
如果(!iterator.MoveNext())
{
屈服断裂;
}
T previous=迭代器.Current;
while(iterator.MoveNext())
{
以前的收益率;
previous=迭代器.Current;
}
}
}

这避免了嵌套太深(如果序列为空,则提前退出),并使用“real”while条件而不是
while(true)

如果使用.NET 3.5,我想您可以使用:

public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source)
{
  return source.TakeWhile((item, index) => index < source.Count() - 1))
}
公共静态IEnumerable SkipLast(此IEnumerable源代码)
{
返回source.TakeWhile((项,索引)=>index
如果您使用的是.NET 3.5,我想您可以使用:

public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source)
{
  return source.TakeWhile((item, index) => index < source.Count() - 1))
}
公共静态IEnumerable SkipLast(此IEnumerable源代码)
{
返回source.TakeWhile((项,索引)=>index
公共静态IEnumerable SkipLast(此IEnumerable源代码)
{
如果(!source.Any())
{
屈服断裂;
}
队列项目=新队列();
items.Enqueue(source.First());