Enumerable.Aggregate错误

时间:2010-12-16 18:52:49

标签: c# .net linq linq-to-objects

一切正常,直到sequentce将唯一的元素传递给此函数。最简单的重现方式是:

var sumOfSquares = Enumerable.Range(5, 1).Aggregate((s, i) => s + i*i);
// sumOfSquares == 5

我认为这个版本的Aggregate应该抛出一个异常,以防序列只包含一个元素。 我是对的还是我错过了一些细节?

4 个答案:

答案 0 :(得分:7)

那应该不会失败。根据{{​​3}}:

  

源的第一个元素用作初始聚合值。

因此,在这种情况下,您只需返回第一个元素(5)并且不执行聚合。没有错误。

正如Anthony Pegram所指出的那样,documentation可以指定聚合的种子值。将种子设置为0会给出答案25,这可能就是您想要的。

var sumOfSquares = Enumerable.Range(5, 1).Aggregate(0, (s, i) => s + i * i);

当然,你不应该使用Aggregate - 你可以使用Sum。

var sumOfSquares = Enumerable.Range(5, 1).Sum(i => i * i);

我想虽然这只是一个简化的例子。

答案 1 :(得分:4)

还有另一种重载,你可以提供适当的种子并获得我认为你想要的结果。

var sumOfSquares = Enumerable.Range(5, 1).Aggregate(0, (s, i) => s + i * i);

在此代码中,0是初始种子,s是累计值,i是当前项。这会产生值25. (5, 2)产生61,(5, 3)产生110,等等。

答案 2 :(得分:0)

为什么要这样?取一个数字的总和是完全有效的。

此外,为了让调用者避免异常,他需要做这样的事情:

public double MySum(IEnumerable<double> seq) {
    switch (seq.Count()) {
        case 0: return 0.0;
        case 1: return seq.First();
        default: return seq.Aggregate((s, i) => s + i);
    }
}

大量的调用,也需要两次(或至少2个第一个元素)传递序列。

答案 3 :(得分:0)

如果你没有提供种子(请参阅Anthony Pegram的答案以获得一个很好的例子),那么Aggregate函数对只有一个项目的IEnumerable几乎没有任何作用。序列中的第一个元素成为种子,IEnumerable中没有其他项目,它将要做什么?因此,如果未指定种子,Aggregate函数将返回第一个元素的值。您可以使用以下编译和运行的代码实际看到它:

var c = 0;
var result = Enumerable.Range(5,1).Aggregate((acc,x) => acc + (x / c));
//result == 5

将其更改为Enumerable.Range(5,2)并立即抛出'除以零'错误。

参考:{备注'部分中的msdn