将 Sum 转换为聚合乘积表达式
我有这样的表达式:
group i by i.ItemId into g
select new
{
Id = g.Key,
Score = g.Sum(i => i.Score)
}).ToDictionary(o => o.Id, o => o.Score);
我想使用Aggregate
来获得数学乘积,而不是g.Sum
。
为了确保它的工作方式与 .Sum
相同(但作为产品),我尝试创建一个仅返回总和的聚合函数...
Score = g.Aggregate(0.0, (sum, nextItem) => sum + nextItem.Score.Value)
但是,这不会给出与使用 相同的结果>.总和
。有知道为什么吗?
nextItem.Score
的类型为 double?
。
I have this expression:
group i by i.ItemId into g
select new
{
Id = g.Key,
Score = g.Sum(i => i.Score)
}).ToDictionary(o => o.Id, o => o.Score);
and instead of g.Sum
I'd like to get the mathematical product using Aggregate
.
To make sure it worked the same as .Sum
(but as product) I tried make an Aggregate function that would just return the sum...
Score = g.Aggregate(0.0, (sum, nextItem) => sum + nextItem.Score.Value)
However, this does not give the same result as using .Sum
. Any idas why?
nextItem.Score
is of type double?
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
问题是,在您的示例中,您从 0.0 开始乘法 - 与零的乘法产生零,最后结果将为零。
正确的是使用乘法的恒等性。虽然在数字上加零会使数字保持不变,但与 1 相乘时,同样的性质也成立。因此,开始乘积聚合的正确方法是从数字 1.0 开始乘法。
The thing is that in your example you are starting the multiplication with 0.0 - A multiplication with zero yields zero, at the end the result will be zero.
Correct is to use the identity property of multiplication. While adding zero to a number leaves the number of unchanged, the same property holds true for a multiplication with 1. Hence, the correct way to start a product aggregate is to kick off multiplication wit the number 1.0.
如果您不确定聚合查询中的初始值并且实际上不需要它(如本例所示),我建议您根本不要使用它。
您可以使用不采用初始值的聚合重载 - http://msdn .microsoft.com/en-us/library/bb549218.aspx
就像这样,
其计算结果为
item1 * (item2 * (item3 * ... * itemN))
。而不是
int Product =equence.Aggregate(1.0, (x, acc) => x * acc);
其计算结果为
1.0 * (item1 * (item2 * (item3 * .. . * 项目N)))
。//编辑:
但有一个重要的区别。当输入序列为空时,前一个确实会抛出 InvalidOperationException。后一个返回种子值,因此为 1.0。
If you aren't sure about initial value in your aggregate query and you don't acutally need one (like in this example) I would recommend you not to use it at all.
You can use Aggregate overload which doesn't take the initial value - http://msdn.microsoft.com/en-us/library/bb549218.aspx
Like this
Which evaluates to
item1 * (item2 * (item3 * ... * itemN))
.instead of
int product = sequence.Aggregate(1.0, (x, acc) => x * acc);
Which evaluates to
1.0 * (item1 * (item2 * (item3 * ... * itemN)))
.//edit:
There is one important difference though. Former one does throw an InvalidOperationException when the input sequence is empty. Latter one returns seed value, therefore 1.0.