你能在一个linq语句中不分组地Sum()多个值吗?

本文关键字:Sum 语句 一个 linq | 更新日期: 2023-09-27 18:08:08

给定类别:

public class FooAmounts
int Id
decimal Month1
decimal Month2
...
decimal Month12
decimal Year2
decimal Year3
decimal Future

我有5个条目的IEnumerable<FooAmounts> (Id的1-5足够有趣!)

我想创建一个新的fooamount,其中每个月/年的总数,但只有其中Id==1 + Id==2例如

var footle = (from f in foolist
where f.Id == 1 || f.Id == 2
select new FooAmounts{
Month1 = Sum(month 1s),
Month2 = Sum(month 2s),
etc etc.
Future = Sum(futures)
).FirstOrDefault();

我正在尝试重新创建这个t-sql:

select SUM(Month1) as Month1, SUM(Month2) as Month2, SUM(Month3) as Month3 from FooAmount where Id=1 or Id=2"

我可以使用group by f.Id into grp子句实现类似的功能,但这让我有两个项目,因此我不能使用First/FoD,这意味着我必须手动将它们相加……看来我一定是漏掉了什么诀窍?

注意:FirstOrDefault()只是在那里,所以我得到一个单一的对象,而不是一个包含一个对象的枚举。我认为(也许是错误的!)这应该总是只返回一个项目…Sum()只有一个结果,无论计算中有多少项。

你能在一个linq语句中不分组地Sum()多个值吗?

不管你有一个值还是多个值,取求和的第一个结果是没有意义的。

如果我有10个人,我可以找到第一个人的年龄,或者我可以找到所有人的年龄的总和——但我找不到第一个年龄的总和。你可以输入:

 var matches = fooList.Where(f => f.Id == 1 || f.Id == 2);
 var sum = new FooAmounts { Month1 = matches.Sum(f => f.Month1),
                            Month2 = matches.Sum(f => f>Month2),
                            ... };

当然,这将多次执行查询。您可以将查询具体化,然后对其进行求和:

 // Materialize the result so we only filter once
 var matches = fooList.Where(f => f.Id == 1 || f.Id == 2).ToList();
 var sum = new FooAmounts { Month1 = matches.Sum(f => f.Month1),
                            Month2 = matches.Sum(f => f>Month2),
                            ... };

或者你也可以使用aggregation:

 var sum = fooList.Where(f => f.Id == 1 || f.Id == 2)
                  .Aggregate(new FooAmounts(), // Seed
                             (sum, item) => new FooAmounts {
                                 Month1 = sum.Month1 + item.Month1,
                                 Month2 = sum.Month2 + item.Month2,
                                 ...
                             });

这将只在序列上迭代一次,并且不会在内存中创建一个大缓冲区,但会在迭代时创建许多FooAmounts实例。

当然可以就地修改累加器:

 var sum = fooList.Where(f => f.Id == 1 || f.Id == 2)
                  .Aggregate(new FooAmounts(), // Seed
                             (sum, item) => {
                                 sum.Month1 += item.Month1;
                                 sum.Month2 += item.Month2;
                                 ...
                                 return sum;
                             });

我觉得有点讨厌,但是并没有真正的有不好的副作用,因为它只是改变了调用中初始化的对象。