你可以在一个linq语句中Sum()多个值...没有分组?

时间:2011-09-11 07:39:59

标签: c# linq sum

鉴于课程:

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

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

我想创建一个新的FooAmounts,每个月/年的总数,但只有Id == 1 + Id == 2 e.g。

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()的结果,无论有多少项进入计算。

1 个答案:

答案 0 :(得分:1)

无论你有一个值还是多个值,取一笔总和的第一个结果都没有意义。

如果我有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),
                            ... };

或者您可以使用聚合:

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

感觉稍微对我很讨厌,但它确实没有副作用,因为它只是改变了在无论如何都要打电话。