你能在一个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()只有一个结果,无论计算中有多少项。
不管你有一个值还是多个值,取求和的第一个结果是没有意义的。
如果我有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;
});
我觉得有点讨厌,但是并没有真正的有不好的副作用,因为它只是改变了调用中初始化的对象。