2011-01-23 37 views
3

我有这样的表达:中g.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数学乘积。

为了确保它的工作一样.Sum(但产品)我试图做一个聚合函数将只返回总和......

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

然而,这并没有给结果作为同使用.Sum。任何idas为什么?

nextItem.Scoredouble?类型。

+3

你不断地问为什么不给相同的结果相加,而是你已经给了我们没有数据说明了问题。 *编写一个简短的程序,清楚地说明我们可以编译,运行和调试*的问题。 – 2011-01-23 16:52:15

回答

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

g是IGrouping类型的,不是IEnumerable,所以我认为这不适用于我的情况。 – Mickel 2011-01-23 15:29:10

+1

是的,它会:'公共接口IGrouping <出TKEY的,出TElement>:IEnumerable的,IEnumerable` – 2011-01-23 17:47:14

1

的事情是,在你的例子你是0.0开始乘法 - 用零乘积生成零,到了最后的结果将是零。

正确的是用乘法的身份属性。虽然在数字中加零使得数字保持不变,但相同的属性适用于与1相乘。因此,启动产品聚合的正确方法是启动数字1.0的乘法运算。

+0

是的,我是知道的(这是一个错字)。但只要看看汇总总计一会儿。它如何不会产生与.Sum()相同的结果? – Mickel 2011-01-23 15:19:40

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.0。