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

发布于 2024-08-19 08:32:18 字数 620 浏览 3 评论 0原文

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

void Summarize(IEnumerable<Section> 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() 重写它(如果适用)?

I have next very non-optimized code:

void Summarize(IEnumerable<Section> 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;
}

How to rewrite such it using IEnumerable.Aggregate(), if applicable?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

痴骨ら 2024-08-26 08:32:18

有时,一个好的老式 foreach 循环是完成这项工作的最佳工具。我认为这里就是这种情况,否则您要么会多次枚举这些部分,要么会出现一些非常不可读的 LINQ 代码。

尽管您可能提前知道sections参数将是一个数组或集合或其他什么,但它可能是枚举非常昂贵的东西或者在枚举之间不能产生一致值的东西。 IEnumerable 有时会让您感到惊讶。

Sometimes a good old fashioned foreach loop is the best tool for the job. I think that's the case here otherwise you're either going to be enumerating the sections multiple times or have some very unreadable LINQ code.

And although you probably know ahead of time that the sections parameter will be an array or collection or what not, it might be something that is very expensive to enumerate or something that doesn't yield consistent values between enumerations. IEnumerable can surprise you sometimes.

诗笺 2024-08-26 08:32:18

我的解决方案与 Codesleuth 的解决方案非常接近,但首先定义一个摘要结构,

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<Section> 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
    });
}

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

my solution is very close to Codesleuth's but would first define a 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<Section> 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
    });
}

Note that the struct would ideally be immutable.

夜司空 2024-08-26 08:32:18
void Summarize(IEnumerable<Section> 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<Section> 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为空,请注意错误。

void Summarize(IEnumerable<Section> 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));
}

How's that?

EDIT:

Ok, I've had a rethink, take a look:

void Summarize(IEnumerable<Section> 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)
        }
    );
}

Beware of errors if sections is empty.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文