首页 / C#开发 / 正文

C#/.NET应用程序编程开发中如何使用LINQ获取泛型集合的最后N个元素?

1783 1 发布于: 2019-07-08 读完约需8分钟

问题描述

C#/.NET应用程序编程开发中,假如当前有一个泛型集合,如何使用LINQ获取这个泛型集合的最后N个元素?

方案一

使用LINQ的扩展方法Skip(),如下:

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

为了重复使用,我们也可以将其他封装成一个静态扩展方法,如下:

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

调用示例:

var collection = new List<T>();
var lastElements = collection.TakeLast(5);

方案二

使用LINQ的扩展方法Reverse()将列表反转,再使用Take()方法取前N个元素,最后再将取出的子集合进行Reverse()即可,扩展方法如下:

public static IEnumerable<T> TakeLast<T>(this IEnumerable<T> coll, int N)
{
    return coll.Reverse().Take(N).Reverse();
}

方案三

封装一个不使用LINQ的扩展方法,如下:

public static class Extensions
{
    public static IEnumerable<T> TakeLast<T>(this IEnumerable<T> collection,
        int n)
    {
        if (collection == null)
            throw new ArgumentNullException("collection");
        if (n < 0)
            throw new ArgumentOutOfRangeException("n", "n must be 0 or greater");

        LinkedList<T> temp = new LinkedList<T>();

        foreach (var value in collection)
        {
            temp.AddLast(value);
            if (temp.Count > n)
                temp.RemoveFirst();
        }

        return temp;
    }
}

调用示例:

IEnumerable<int> sequence = Enumerable.Range(1, 10000);
IEnumerable<int> last10 = sequence.TakeLast(10);

方案四

另一个不使用LINQ封装的扩展方法,如下:

public static class TakeLastExtension
{
    public static IEnumerable<T> TakeLast<T>(this IEnumerable<T> source, int takeCount)
    {
        if (source == null) { throw new ArgumentNullException("source"); }
        if (takeCount < 0) { throw new ArgumentOutOfRangeException("takeCount", "must not be negative"); }
        if (takeCount == 0) { yield break; }

        T[] result = new T[takeCount];
        int i = 0;

        int sourceCount = 0;
        foreach (T element in source)
        {
            result[i] = element;
            i = (i + 1) % takeCount;
            sourceCount++;
        }

        if (sourceCount < takeCount)
        {
            takeCount = sourceCount;
            i = 0;
        }

        for (int j = 0; j < takeCount; ++j)
        {
            yield return result[(i + j) % takeCount];
        }
    }
}

调用示例:

List<int> l = new List<int> {4, 6, 3, 6, 2, 5, 7};
List<int> lastElements = l.TakeLast(3).ToList();

方案五

使用LINQ的扩展方法SkipWhile,如下:

public static IEnumerable<T> TakeLastN<T>(this IEnumerable<T> source, int n)
{
    if (source == null)
        throw new ArgumentNullException("Source cannot be null");

    int goldenIndex = source.Count() - n;
    return source.SkipWhile((val, index) => index < goldenIndex);
}

版权声明:本作品系原创,版权归码友网所有,如未经许可,禁止任何形式转载,违者必究。

上一篇: [SQL Server]SQL Server数据库中如何使用SQL语句删除指定数据库所有的数据表、视图、存储过程、触发器、主键、外键、约束以及所有的依赖关系等等?

下一篇: C#/.NET应用程序编程开发中使用AutoMapper时如何忽略某个或某些属性的映射?

本文永久链接码友网 » C#/.NET应用程序编程开发中如何使用LINQ获取泛型集合的最后N个元素?

分享扩散:

发表评论

登录用户才能发表评论, 请 登 录 或者 注册