阅读这篇文章关于Scala http://josephmoniz.github.io/blog/2013/04/04/scala-reduce-vs-fold/中的reduce vs fold,它指出"你正在取一些N的值并对它执行聚合操作,使得最终结果通常是某个值< = N "
但是这个陈述是错误的,因为对N个值进行求和会产生一个值> = N?
更新:我认为< =在这种情况下意味着相同的类型或子类型
答案 0 :(得分:20)
我认为这是一个有缺陷的表征。想到这样的折叠会更好:
In:
initial value
way to combine stuff with initial value
collection
Out:
combined stuff
并且减少是这样的:
In:
way to combine stuff
collection
Out:
combined stuff
也就是说,不同之处在于你是否有一个初始值(它可能与你在集合中所拥有的类型不同!),折叠,或者你是否只是折叠值你已经拥有,就像减少一样。
如果你有一个自然的零点,即可以在不改变它的组合的情况下组合的东西,那么你可以从零开始实现reduce作为折叠。例如,对于乘法,零是1
(因为1*x == x
),所以
List(1,2,3).fold(1){_ * _}
List(1,2,3).reduce{_ * _}
给出相同的答案。 (但是,只有第一个在空列表中给出答案!)
要看一个折叠如何更加通用的示例,请考虑这个 - 这里有一个foldLeft,所以我们知道在操作的左侧传递初始值 -
List(1,2,3).foldLeft(List(0))((ns,n) => ns ++ List.fill(n+1)(n))
给出了List(0, 1, 1, 2, 2, 2, 3, 3, 3, 3)
。
答案 1 :(得分:3)
reduce
使用名为" monoid"获得零价值"作为fold *
答案 2 :(得分:3)
折叠需要提供“起始元素”,减少会自动将序列的第一个元素作为开始,所以它们在某种程度上是等价的:
val L = List(1,2,3,4)
val H = L.head
val T = L.tail
L.reduce(_+_) ~== T.fold(H)(_+_)
减少更紧凑,但有折叠,你有能力提供不同的开始元素和更改操作的结果,所以:
2014 + L.reduce(_+_) ~== L.fold(2014)(_+_) // NB: here we use L, not T for fold
当你从简单的算术中走出一些更复杂的二元运算,如Set + Int时,事情会变得更令人兴奋,更有利于折叠:
List(1,2,3,3,2,2,1).foldLeft(Set[Int]())(_ + _) // will produce Set(1, 2, 3)
...您可以折叠JDBC更新调用:)。
答案 3 :(得分:0)