c# – 如何使用LINQ序列中除了最后一个元素之外的所有元素?

假设我有一个序列。

IEnumerable<int> sequence = GetSequenceFromExpensiveSource();
// sequence now contains: 0,1,2,3,...,999999,1000000

获取序列不便宜,并且是动态生成的,我想只通过它一次。

我想得到0 – 999999(即除了最后一个元素之外的所有东西)

我知道我可以做一些事情:

sequence.Take(sequence.Count() - 1);

但是导致大序列上的两个枚举。

有一个LINQ结构,让我做:

sequence.TakeAllButTheLastElement();
最佳答案
我不知道Linq解决方案 – 但你可以很容易地编码算法自己使用generator(yield return)。

public static IEnumerable<T> TakeAllButLast<T>(this IEnumerable<T> source) {
    var it = source.GetEnumerator();
    bool hasRemainingItems = false;
    bool isFirst = true;
    T item = default(T);

    do {
        hasRemainingItems = it.MoveNext();
        if (hasRemainingItems) {
            if (!isFirst) yield return item;
            item = it.Current;
            isFirst = false;
        }
    } while (hasRemainingItems);
}

static void Main(string[] args) {
    var Seq = Enumerable.Range(1, 10);

    Console.WriteLine(string.Join(", ", Seq.Select(x => x.ToString()).ToArray()));
    Console.WriteLine(string.Join(", ", Seq.TakeAllButLast().Select(x => x.ToString()).ToArray()));
}

或者作为一个广义的解决方案,丢弃最后n项(使用队列,如在评论中建议的):

public static IEnumerable<T> SkipLastN<T>(this IEnumerable<T> source, int n) {
    var  it = source.GetEnumerator();
    bool hasRemainingItems = false;
    var  cache = new Queue<T>(n + 1);

    do {
        if (hasRemainingItems = it.MoveNext()) {
            cache.Enqueue(it.Current);
            if (cache.Count > n)
                yield return cache.Dequeue();
        }
    } while (hasRemainingItems);
}

static void Main(string[] args) {
    var Seq = Enumerable.Range(1, 4);

    Console.WriteLine(string.Join(", ", Seq.Select(x => x.ToString()).ToArray()));
    Console.WriteLine(string.Join(", ", Seq.SkipLastN(3).Select(x => x.ToString()).ToArray()));
}

转载注明原文:c# – 如何使用LINQ序列中除了最后一个元素之外的所有元素? - 代码日志