从C#列表中抓取最后n个项目

时间:2016-09-05 14:56:08

标签: c#

我有一个C#List<T>个项目。我想从某个索引迭代到List<T>项的末尾。我可以使用 foreach 语法执行此操作吗?

 List<T> list = ...

 foreach (var item in ???) 
 {
    ...
 }

或任何其他方法?

e.g。从List.Count - 50到结尾(我只想要最后 50项目)

5 个答案:

答案 0 :(得分:7)

由于Skip实际枚举项目,因此List<T>的效率不高:

    public static IEnumerable<TSource> Skip<TSource>(this IEnumerable<TSource> source, int count) {
        if (source == null) throw Error.ArgumentNull("source");
        return SkipIterator<TSource>(source, count);
    }

    ...

    static IEnumerable<TSource> SkipIterator<TSource>(IEnumerable<TSource> source, int count) {
        using (IEnumerator<TSource> e = source.GetEnumerator()) {
            while (count > 0 && e.MoveNext()) count--;
            if (count <= 0) {
                while (e.MoveNext()) yield return e.Current;
            }
        }
    }

参见参考来源http://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,90ccdbd47b57182e 详情;如果初始列表很长,我建议使用 for loop 并模拟 foreach 一个:

// the simplest in case list.Count >= 50 
// foreach (var item in ...) {...} emulation
for (int i = list.Count - 50; i < list.Count; ++i) {
  var item = list[i];

  ...
}

对于任意大小的列表(可以有更少的tan 50项目)

for (int i = Math.Max(list.Count - 50, 0); i < list.Count; ++i) {
  var item = list[i];

  ...
}

答案 1 :(得分:6)

尝试:

foreach (var item in list.Skip(Math.Max(0, list.Count - 50)))

如果您知道列表长度至少为50,则可以避免范围检查:

foreach (var item in list.Skip(list.Count-50))

虽然我确实只是写了for循环并避免任何花哨的东西:

for (int i = Math.Max(0, list.Count - 50); i < list.Count; ++i)
{
    // Do something with list[i]
}

非范围检查版本:

for (int i = list.Count-50; i < list.Count; ++i)
{
    // Do something with list[i]
}

答案 2 :(得分:4)

尝试使用以下内容:

newList = Enumerable.Reverse(list).Take(50).Reverse().ToList();

答案 3 :(得分:2)

鉴于您有一个IList<T>(假设来自您的散文),那么您可以使用for循环轻松抓取最后一个n。这仍然会像LINQ -

那样被懒惰地评估
public static IEnumerable<T> LastN<T>(this IList<T> list, int n)
{
    if (list == null) 
    {
        throw new ArgumentNullException("list");
    }

    if (list.Count - n < 0) 
    {
        n = list.Count;
    }

    for (var i = list.Count - n; i < list.Count; i++) 
    {
        yield return list[i];
    }
}

// use 
var tail50 = myList.LastN(50); 

这也非常适合ICollection<T>

有一些实现ICollection<T>的集合类型,例如LinkedList<T>,如果你知道它们的具体类型,可能会有更有效的方法来完成你需要的东西。 (在这种情况下,对于LinkedList<T>,上面的代码通常效率低下。

使用集合时要记住的一件事是IEnumerable<T>以及它是无限序列的可能性。在这些情况下,除非你知道IEnumerable<T>的具体类型或通过其他方式知道它是有限的,否则最好重新考虑获得&#34;最后n项&#34;,因为它甚至可能不可能。

答案 4 :(得分:1)

myList.Reverse();          // Reverse the list
lastFive = myList.Take(5); // Take the first 5 elements from the list.
myList.Reverse();          // Restore the list to its original order.