如何使用LINQ获取序列中除最后一个元素之外的所有元素?
如何使用LINQ获取序列中除最后一个元素之外的所有元素?
假设我有一个序列。
IEnumerable sequence = GetSequenceFromExpensiveSource(); // sequence now contains: 0,1,2,3,...,999999,1000000
获取序列的成本很高,而且是动态生成的,我想只迭代一次。
我想获取0-999999(即除了最后一个元素之外的所有内容)
我知道我可以做类似以下操作:
sequence.Take(sequence.Count() - 1);
但这会导致两个枚举器遍历大序列。
是否有LINQ构造使我这样做:
sequence.TakeAllButTheLastElement();
admin 更改状态以发布 2023年5月22日
我不知道Linq解决方案 - 但是你可以使用生成器(yield return)很容易地编写算法。
public static IEnumerableTakeAllButLast (this IEnumerable 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 IEnumerableSkipLastN (this IEnumerable source, int n) { var it = source.GetEnumerator(); bool hasRemainingItems = false; var cache = new Queue (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())); }
Enumerable.SkipLast(IEnumerable
方法是在.NET Standard 2.1中添加的,正好可以满足您的需要。
IEnumerablesequence = GetSequenceFromExpensiveSource(); var allExceptLast = sequence.SkipLast(1);
来源自https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.skiplast
返回一个新的可枚举集合,该集合包含源集合中省略了最后count个元素后的元素。