“Fold” LINQ扩展方法在哪里?

103

我在MSDN的Linq示例中找到了一个很不错的方法叫做Fold(),我想要使用它。他们的例子:

double[] doubles = { 1.7, 2.3, 1.9, 4.1, 2.9 }; 
double product = 
     doubles.Fold((runningProduct, nextFactor) => runningProduct * nextFactor); 

很不幸,我无法使其编译通过,无论是在他们的示例中还是在我的自己代码中,并且我在MSDN中找不到任何其他地方提到这个方法(例如Enumerable或Array扩展方法)。我得到的错误是一个普通的“不知道那个”的错误:

error CS1061: 'System.Array' does not contain a definition for 'Fold' and no 
extension method 'Fold' accepting a first argument of type 'System.Array' could 
be found (are you missing a using directive or an assembly reference?)

我正在使用其他方法,我相信这些方法来自于Linq(如Select()和Where()),并且我已经"using System.Linq",所以我认为一切都没问题。

这个方法在C# 3.5中真的存在吗?如果存在,那么我做错了什么?


3
请查看你引用的示例页面上的“面包屑导航”——它将C# 3称为未来产品。未来的产品通常在发货前会有所变化。像其他人提到的一样,请查看Enumerable.Aggregate并尽情使用。 :) *Visual C# 开发人员中心 > 主页 > 产品信息 > 未来版本 > 101个LINQ示例 > 聚合运算符 - Curt Nichols
2个回答

138
您需要使用Aggregate扩展方法:
double product = doubles.Aggregate(1.0, (prod, next) => prod * next);

查看MSDN获取更多信息。它允许你指定一个种子,然后使用表达式计算连续的值。


5
请注意,您不必拥有一个种子。如果调用没有种子的重载,则会使用列表中的第一个元素作为初始聚合值,并且只有在到达第二个元素时才调用 Func。请参阅:https://msdn.microsoft.com/en-us/library/vstudio/bb548651(v=vs.110).aspx - Josh Gallagher
如果我理解正确的话,这不是折叠操作 :/ 折叠操作应该接受两个不同类型的参数。例如,第一个参数可以使用字符串,第二个参数可以使用任何具有 ToString() 方法的对象,从而返回整个容器的文本表示形式。 - Hi-Angel
@Hi-Angel,不,实际上这个例子是一个fold。<double>类型参数只是由编译器自动推断出来的,因此并不是必需的。 - kdbanman
@kdbanman 不,你没有理解我的意思,但事实上你是对的——这个例子是fold的一个部分案例,尽管当我留下评论时,我需要一个更强大的fold。在*伪C#*中,我需要的东西看起来像array.Aggregate("", (p, elem) => String.Concat(p, elem.ToString()))。但我认为这在C#的弱类型系统中是不可能的。更新:为了更清楚:伪代码示例使用一个函数对数组进行折叠,该函数将字符串作为第一个参数,数组元素作为第二个参数;从而生成容器的字符串表示形式。 - Hi-Angel
2
@Hi-Angel,pelem可以是您喜欢的任何类型。请参见此重载,并查看此示例 - kdbanman
1
@kdbanman 嗯,⁺¹,为什么以前我用的时候它没起作用真的很有趣... :/ 你是对的,它确实有效。 - Hi-Angel

43

Fold(又称Reduce)是函数式编程中的标准术语。因为某种原因,在LINQ中它被命名为Aggregate

double product = doubles.Aggregate(1.0, (runningProduct, nextFactor) => runningProduct* nextFactor);

9
“Aggregate” 是面向对象编程和 SQL 领域中更为常见的术语。 - Adam Robinson
4
不知道CREATE AGGREGATE关键字(http://msdn.microsoft.com/en-us/library/ms182741.aspx),每天都会学到新的东西。 - Richard Berg
5
有趣的是,我从未在SQL之外听说过“aggregate”。维基百科上有一个列表(http://en.wikipedia.org/wiki/Fold_(higher-order_function))列出了几十种语言,而C#是唯一将其称为“Aggregate”的语言。 "Reduce" 是明显的胜者,其次是 ML 家族的 "Fold",Smalltalk 和其它语言中则是 "Inject"。 - Ken
12
名称与其功能相关,实现方式并不重要。另外,左折叠在可能的情况下通常是通过尾递归在函数式语言中进行实现。而C#没有右折叠,这在某种程度上是选择了一个愚蠢的名称的结果——尽管比“select”用于“map”的名称不那么糟糕——并忽略了现有的函数式技术。至于在面向对象领域中,“Aggregate”是否更熟悉……根本不是。 - Jim Balter
10
公正地说,我认为这不是微软无视现有的功能性技术或术语,而是其面向数据库访问和SQL术语的取向,许多企业程序员可能比函数式编程术语更熟悉。 - RavuAlHemio
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接