使用第一对作为种子进行聚合

And*_*ren 1 c# linq aggregate

有什么方法可以聚合(折叠)这个序列

{ a, b, c, d }
Run Code Online (Sandbox Code Playgroud)

有一个函数f(x,y)所以我最终得到f(f(f(a,b),c),d)

result = f(a,b)
result = f(result, c)
result = f(result, d)
Run Code Online (Sandbox Code Playgroud)

目前我这样做(假设列表长度>= 2):

var seed = f(list[0], list[1]);
var result = list.Skip(2).Aggregate(seed, f);
Run Code Online (Sandbox Code Playgroud)

我可以用一个表达式表达同样的事情吗?

编辑:假设 的结果的类型f元素类型不同,并且 没有好的“零元素” ,即一个好的种子值使得。零元素运算的示例包括加法(零元素= )、乘法(零元素= )、列表串联(零元素= )。ff(0, a) = a01[]

没有好的零元素的操作的一个例子是平均值,即

result = avg(a,b)
result = avg(result, c)
result = avg(result, d)
Run Code Online (Sandbox Code Playgroud)

此折叠的唯一有效种子是avg(a,a)avg(a,b)。所以对于函数avg和输入序列{a, b, c, d}我想要result = avg(avg(avg(a,b),c),d)

Ere*_*mez 5

Aggregate已经将聚合函数应用于第一对,因此您不需要将它们分开:

var result = list.Aggregate((a,b) => f(a,b));
Run Code Online (Sandbox Code Playgroud)

但是,如果累积值的类型与集合元素的类型不同,则您不能使用上面的重载(这可能就是您问这个问题的原因)。您可以从种子值“零”开始,这允许您仅从第一个元素开始,并且不需要Skip

Func<int, string, int> f = (a, b) => a + b.Length;
var list = new[] { "1", "12", "123", "1234" };
var seed = 0;
var result = list.Aggregate(seed, (a, b) => f(a, b));
Run Code Online (Sandbox Code Playgroud)