将Sum转换为Aggregate产品表达式

时间:2011-01-23 13:25:52

标签: c# linq aggregate aggregate-functions

我有这个表达:

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

而不是g.Sum我想使用Aggregate来获取数学产品。

为了确保它与.Sum(但作为产品)的工作方式相同,我尝试制作一个只返回总和的聚合函数...

Score = g.Aggregate(0.0, (sum, nextItem) => sum + nextItem.Score.Value)

但是,这与使用.Sum的结果不同。任何idas为什么?

nextItem.Score的类型为double?

3 个答案:

答案 0 :(得分:3)

public static class MyExtensions
{
    public static double Product(this IEnumerable<double?> enumerable)
    {
        return enumerable
          .Aggregate(1.0, (accumulator, current) => accumulator * current.Value);
    }
}

答案 1 :(得分:1)

事实是,在你的例子中,你开始乘以0.0 - 乘以零得到零,最后结果将为零。

正确的是使用乘法的identity属性。虽然向数字加零会使数字保持不变,但相同的属性适用于乘以1。因此,启动产品聚合的正确方法是以数字1.0开始乘法。

答案 2 :(得分:0)

如果您不确定汇总查询中的初始值,并且您实际上并不需要(例如此示例),我建议您根本不要使用它。

您可以使用不会取初始值的聚合重载 - http://msdn.microsoft.com/en-us/library/bb549218.aspx

喜欢这个

int product = sequence.Aggregate((x, acc) => x * acc);

评估为item1 * (item2 * (item3 * ... * itemN))

而不是

int product = sequence.Aggregate(1.0, (x, acc) => x * acc);

评估为1.0 * (item1 * (item2 * (item3 * ... * itemN)))

//编辑: 但是有一个重要的区别。当输入序列为空时,前者会抛出InvalidOperationException。后者1返回种子值,因此为1.0。