一尘不染

使用Linq获取集合的最后N个元素?

c#

给定一个集合,有没有办法获取该集合的最后N个元素?如果框架中没有方法,那么编写扩展方法来执行此操作的最佳方法是什么?


阅读 319

收藏
2020-05-19

共1个答案

一尘不染

collection.Skip(Math.Max(0, collection.Count() - N));

这种方法保留了项目顺序,而无需依赖任何排序,并且在多个LINQ提供程序之间具有广泛的兼容性。

重要的是要注意不要以Skip负数呼叫。某些提供程序(例如,实体框架)在出现负参数时将产生ArgumentException。呼吁Math.Max巧妙地避免这种情况。

下面的类具有扩展方法的所有基本要素,这些要素是:静态类,静态方法和this关键字的使用。

public static class MiscExtensions
{
    // Ex: collection.TakeLast(5);
    public static IEnumerable<T> TakeLast<T>(this IEnumerable<T> source, int N)
    {
        return source.Skip(Math.Max(0, source.Count() - N));
    }
}

关于性能的简要说明:

因为对的调用Count()可能导致某些数据结构的枚举,所以此方法具有导致两次通过数据的风险。对于大多数枚举对象而言,这并不是真正的问题。实际上,已经存在针对列表,数组甚至EF查询的优化,以评估Count()O(1)时间的操作。

但是,如果必须使用仅向前枚举,并且希望避免进行两次遍历,请考虑像Lasse V.
Karlsen
Mark
Byers
这样描述的一次遍历算法。这两种方法都使用临时缓冲区在枚举时保存项目,一旦找到集合的末尾便会产生这些项目。

2020-05-19