C#:SkipLast实现 [英] C#: SkipLast implementation

查看:282
本文介绍了C#:SkipLast实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要一种方法来给我除序列中的最后一个项目以外的所有项目.这是我当前的实现:

I needed a method to give me all but the last item in a sequence. This is my current implementation:

    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;
                }
        }
    }

我需要做的是对除最后一个项目以外的所有项目进行处理.就我而言,我有一系列具有各种属性的对象.然后,我按日期对它们进行排序,然后我需要对所有这些元素进行调整,但最新的项目除外(该项目将是订购后的最后一个项目).

What I need it for is to do something with all the items except the last one. In my case I have a sequence of objects with various properties. I then order them by date, and then I need to do an adjustment to all of them except the most recent item (which would be the last one after ordering).

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

Thing is, I am not too into these enumerators and stuff yet and don't really have anyone here to ask either :p What I am wondering is if this is a good implementation, or if I have done a small or big blunder somewhere. Or if maybe this take on the problem is a weird one, etc.

我猜想更通用的实现可能是AllExceptMaxBy方法.既然是这样的话. MoreLinq 具有MaxByMinBy方法,而我的方法类型需要执行相同的操作,但返回除最大或最小项之外的所有项.

I guess a more general implementation could have been an AllExceptMaxBy method. Since that is kind of what it is. The MoreLinq has a MaxBy and MinBy method and my method kind of need to do the same, but return every item except the maximum or minimum one.

推荐答案

这很棘手,因为最后一个元素"不是马尔可夫停止点:您不能说直到最后一个元素尝试获得下一个.这是可行的,但前提是您不介意永久地成为背后的一个要素".基本上,这就是您当前的实现所要做的,而且看起来还可以,尽管我可能会写得有些不同.

This is tricky, as "last element" isn't a Markov stopping point: you can't tell that you've got to the last element until you try to get the next one. It's doable, but only if you don't mind permanently being "one element behind". That's basically what your current implementation does, and it looks okay, although I'd probably write it slightly differently.

另一种方法是使用foreach,除非您是第一次迭代,否则总是产生以前返回的值:

An alternative approach would be to use foreach, always yielding the previously returned value unless you were at the first iteration:

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;
    }
}

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

Another option, closer to your code:

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)

That avoids nesting quite as deeply (by doing an early exit if the sequence is empty) and it uses a "real" while condition instead of while(true)

这篇关于C#:SkipLast实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆