使用LINQ从文件中有效地计算总计

时间:2015-08-12 10:36:29

标签: c# linq

我正在阅读一个文件并将其中的每一行转换为一个类,我们称之为Record,然后使用Record和{{1}返回每个IEnumerable<Record> }}

因此,每当我对枚举执行操作时,我才开始实际执行这些读取,例如对其执行求和或使用yield return迭代它。

我确实需要浏览每条记录,然后将其转换为数据库,但由于数据库设计在我的时间之前我需要数据库中每条记录的总计,所以我需要这些总数在我开始将它们翻译成我的数据库之前。

目前,在我开始迭代枚举(例如foreach.Count())之前,我的枚举上有五个单独的.Sum()int i = records.Sum(r => r.SomeField)操作。这些计数或总和中的每一个将遍历整个文件以分别计算每个。我对这种行为并不满意,并希望找到一种更有效的方法。

如果有任何不同,我使用的是.NET 3.5。

2 个答案:

答案 0 :(得分:1)

您可以使用自己的struct在可通过可枚举对象的单次传递中计算一些值。

public struct ComplexAccumulator
{
    public int TotalSumField { get; set; }

    public int CountSomethingTrue { get; set; }
}

现在,您可以使用Aggreagate扩展方法来累积值:

records.Aggregate(default(ComplexAccumulator), (a, r) => new ComplexAccumulator
{
    TotalSumFiled = a.TotalSumField + r.SumField,
    CountSomethingTrue = a.CountSomethingTrue + r.IsSomethingTrue ? 1 : 0,
});

您可以使用合适的struct实例代替Tuple,而不是Tuple<int, int, int>。类似于add

答案 1 :(得分:0)

效率不是LINQ的优势......你需要在这里用手动循环替换一些LINQ东西。

您似乎需要两次通过数据。一个用于汇总:

var sum = 0; //etc.
foreach (var item in items) {
 //compute all 5 aggregates here
}

然后一个人翻译数据:

items.Select(item => Translate(item, aggregates))

是否应缓冲items(例如使用ToList)取决于可用内存是否可以容纳这些项目。

您可以使用Aggregate在一次通过中执行所有5个聚合,但这并不比循环更好。它更慢,代码更多,代码可以说是难以理解的。