当前位置:  开发笔记 > 编程语言 > 正文

提高LINQ性能

如何解决《提高LINQ性能》经验,为你挑选了2个好方法。

我有这样的linq语句:

var records = from line in myfile 
              let data = line.Split(',')
              select new { a=int.Parse(data[0]), b=int.Parse(data[1]) };
var average = records.Sum(r => r.b)!=0?records.Sum(r => r.a) / records.Sum(r => r.b):0;

我的问题是:记录的次数是多少次.(r => rb)是在最后一行计算的?LINQ是否每次需要计算总和时都会遍历所有记录(在这种情况下,3 Sum()所以循环3次)?或者只巧妙地循环所有记录一次并计算所有总和?


编辑1:

    我想知道是否有任何方法可以通过仅仅浏览一次所有记录来改进它(因为我们只需要在使用plain for循环时在单个循环中执行它)?

    我们实在没有必要都加载到内存之前,我们能做的总和与平均值.当然,我们可以在从文件加载每个元素时对它们求和.有没有办法减少内存消耗?


编辑2

只是为了澄清一下,在我结束之前我没有使用LINQ.使用plain while/for循环可以实现所有性能要求.但我接着尝试通过使用LINQ来提高可读性并减少代码行.似乎我们无法同时获得两者.



1> mybirthname..:

两次,写这样,它将是一次:

var sum = records.Sum(r => r.b);

var avarage = sum != 0 ? records.Sum(r => r.a)/sum: 0;


嘿,两次仍比三次好,amirite?

2> Cameron..:

很多答案,但没有一个能够解决你的所有问题.

记录的次数是多少次.(r => rb)是在最后一行计算的?

三次.

LINQ是否每次需要计算总和时都会遍历所有记录(在这种情况下,3 Sum()所以循环3次)?

是.

或者只巧妙地循环所有记录一次并计算所有总和?

没有.

我想知道是否有任何方法可以通过仅仅浏览一次所有记录来改进它(因为我们只需要在使用plain for循环时在单个循环中执行它)?

你可以这样做,但它需要你急切地加载所有与你的下一个问题相矛盾的数据.

在我们完成总和和平均之前,确实没有必要将所有内容加载到内存中.当然,我们可以在从文件加载每个元素时对它们求和.有没有办法减少内存消耗?

那是对的.在你的原始帖子中,你有一个被调用的变量myFile,你正在迭代它并将它放入一个名为line(读:基本上是a foreach)的局部变量中.由于您没有显示您获取myFile数据的方式,我假设您正在急切地加载所有数据.

这是一个延迟加载数据的快速示例:

public IEnumerable GetData()
{
    using (var fileStream = File.OpenRead(@"C:\Temp\MyData.txt"))
    {
        using (var streamReader = new StreamReader(fileStream))
        {
            string line;
            while ((line = streamReader.ReadLine()) != null)
            {                       
                yield return line;
            }
        }
    }
}

public void CalculateSumAndAverage()
{
    var sumA = 0;
    var sumB = 0;
    var average = 0;

    foreach (var line in GetData())
    {
        var split = line.Split(',');
        var a = Convert.ToInt32(split[0]);
        var b = Convert.ToInt32(split[1]);

        sumA += a;
        sumB += b;
    }

    // I'm not a big fan of ternary operators,
    // but feel free to convert this if you so desire.
    if (sumB != 0)
    {
        average = sumA / sumB;
    }
    else 
    {
        // This else clause is redundant, but I converted it from a ternary operator.
        average = 0;
    }
}

推荐阅读
mylvfamily
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有