如何使用Aggregate()将几个独立的LINQ查询重写为单个查询?

我有下一个非优化的代码:

void Summarize(IEnumerable
sections) { this.DateBegin = sections.Select(s => s.Date).Min(); this.DateEnd = sections.Select(s => s.Date).Max(); this.Income = sections.Where(s => s.IsIncome).Sum(r => r.Amount); this.ExpenditureBank = sections.Where(s => s.IsExpenditureBank).Sum(r => r.Amount); this.ExpenditureClient = sections.Where(s => s.IsExpenditureClient).Sum(r => r.Amount); this.Expenditure = this.ExpenditureBank + this.ExpenditureClient; }

如果适用,如何使用IEnumerable.Aggregate()重写它?

有时,一个好的老式foreach循环是这项工作的最佳工具。 我认为就是这种情况,否则你要么多次枚举这些部分,要么有一些非常难以理解的LINQ代码。

虽然你可能提前知道sections参数将是一个数组或集合或者不是,但它可能是枚举非常昂贵的东西,或者在枚举之间不会产生一致值的东西。 IEnumerable有时会让你大吃一惊。

我的解决方案非常接近Codesleuth,但首先会定义一个Summary Struct

 struct Summary { public DateTime DateBegin {get; set;} public DateTime DateEnd {get; set;} public int Income {get; set;} public int ExpenditureBank {get; set;} public int ExpenditureClient {get; set;} public int Expenditure {get {return ExpenditureBank+ExpenditureClient; }} } void Summarize(IEnumerable
sections) { var result = sections.Aggregate(new Summary { DateBegin = DateTime.MaxValue, DateEnd = DateTime.MinValue, Income = 0, ExpenditureBank =0, ExpenditureClient =0, }, (agg, next) => new Summary { DateBegin = next.Date < agg.DateBegin ? next.Date : agg.DateBegin, DateEnd = next.Date > agg.DateEnd ? next.Date : agg.DateEnd, Income = agg.Income + (next.IsIncome ? next.Amount : 0), ExpenditureBank = next.IsExpenditureBank ? next.Amount: 0, ExpenditureClient = next.IsExpenditureClient ? next.Amount : 0 }); }

请注意,结构理想情况下是不可变的。

 void Summarize(IEnumerable
sections) { this.DateBegin = sections.Select(s => s.Date).Min(); this.DateEnd = sections.Select(s => s.Date).Max(); this.Income = sections.Where(s => s.IsIncome).Sum(r => r.Amount); this.Expenditure = sections.Aggregate(0, (agg, next) => agg += (next.IsExpenditureBank ? next.Amount : 0) + (next.IsExpenditureClient ? next.Amount : 0)); }

怎么样?

编辑:

好的,我有一个重新思考,看看:

 void Summarize(IEnumerable
sections) { var result = sections.Aggregate(new { DateBegin = DateTime.MaxValue, DateEnd = DateTime.MinValue, Income = 0, Expenditure = 0 }, (agg, next) => new { DateBegin = next.Date < agg.DateBegin ? next.Date : agg.DateBegin, DateEnd = next.Date > agg.DateEnd ? next.Date : agg.DateEnd, Income = agg.Income + (next.IsIncome ? next.Amount : 0), Expenditure = agg.Expenditure + (next.IsExpenditureBank ? next.Amount : 0) + (next.IsExpenditureClient ? next.Amount : 0) } ); }

如果sections是空的,请注意错误。