c# – 将列表细分为多个列表时System.Linq的性能问题

我写了一个方法,使用System.
Linq将项目列表细分为多个列表.

当我为50000个简单整数运行此方法时,它需要大约59.862秒.

Stopwatch watchresult0 = new Stopwatch();
watchresult0.Start();
var result0 = SubDivideListLinq(Enumerable.Range(0, 50000), 100).ToList();
watchresult0.Stop();
long elapsedresult0 = watchresult0.ElapsedMilliseconds;

所以我试着提升它,并用一个简单的循环来编写它,迭代我列表中的每个项目,它只需要4毫秒:

Stopwatch watchresult1 = new Stopwatch();
watchresult1.Start();
var result1 = SubDivideList(Enumerable.Range(0, 50000), 100).ToList();
watchresult1.Stop();
long elapsedresult1 = watchresult1.ElapsedMilliseconds;

这是我使用Linq的Subdivide方法:

private static IEnumerable<List<T>> SubDivideListLinq<T>(IEnumerable<T> enumerable, int count)
{
    while (enumerable.Any())
    {
        yield return enumerable.Take(count).ToList();
        enumerable = enumerable.Skip(count);
    }
}

这是我的Subdivide方法,每个项目都有foreach循环:

private static IEnumerable<List<T>> SubDivideList<T>(IEnumerable<T> enumerable, int count)
{
    List<T> allItems = enumerable.ToList();

    List<T> items = new List<T>(count);
    foreach (T item in allItems)
    {
        items.Add(item);

        if (items.Count != count) continue;
        yield return items;
        items = new List<T>(count);
    }

    if (items.Any())
        yield return items;
}

你有任何想法,为什么我自己的实现比用Linq划分要快得多?或者我做错了什么?

并且:正如您所看到的,我知道如何拆分列表,因此这不是相关问题的重复.我想知道linq和我的实现之间的性能.不是如何拆分列表

最佳答案 如果您追求可读性和性能您可能希望使用此算法.在速度方面,这个非常接近你的非linq版本.同时它更具可读性.

private static IEnumerable<List<T>> SubDivideListLinq<T>(IEnumerable<T> enumerable, int count)
{
    int index = 0;
    return enumerable.GroupBy(l => index++/count).Select(l => l.ToList());
}

它的替代方案:

private static IEnumerable<List<T>> SubDivideListLinq<T>(IEnumerable<T> enumerable, int count)
{
    int index = 0;
    return from l in enumerable
        group l by index++/count
        into l select l.ToList();
}

另一种选择:

private static IEnumerable<List<T>> SubDivideListLinq<T>(IEnumerable<T> enumerable, int count)
{
    int index = 0;
    return enumerable.GroupBy(l => index++/count, 
                             item => item, 
                             (key,result) => result.ToList());
}

在我的电脑中,我得到linq 0.006秒对非linq 0.002秒,这是完全公平的并且可以使用linq.

作为建议,不要用微优化代码折磨自己.显然没有人会感觉到几毫秒的差异,所以写一个代码,以后你和其他人可以轻松理解.

点赞