如何使用 LINQ 获取序列中除最后一个元素之外的所有元素? [英] How to take all but the last element in a sequence using LINQ?
问题描述
假设我有一个序列.
IEnumerable<int> sequence = GetSequenceFromExpensiveSource();
// sequence now contains: 0,1,2,3,...,999999,1000000
获取序列并不便宜,而且是动态生成的,我只想遍历一次.
Getting the sequence is not cheap and is dynamically generated, and I want to iterate through it once only.
我想得到 0 - 999999(即除最后一个元素之外的所有内容)
I want to get 0 - 999999 (i.e. everything but the last element)
我意识到我可以执行以下操作:
I recognize that I could do something like:
sequence.Take(sequence.Count() - 1);
但这会导致对大序列进行两次枚举.
but that results in two enumerations over the big sequence.
是否有一个 LINQ 结构可以让我这样做:
Is there a LINQ construct that lets me do:
sequence.TakeAllButTheLastElement();
推荐答案
我不知道 Linq 解决方案 - 但是您可以使用生成器(收益率)轻松地自己编写算法.
I don't know a Linq solution - But you can easily code the algorithm by yourself using generators (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 项的通用解决方案(使用如评论中建议的队列):
Or as a generalized solution discarding the last n items (using a queue like suggested in the comments):
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()));
}
这篇关于如何使用 LINQ 获取序列中除最后一个元素之外的所有元素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!