减少和折叠之间的差异

时间:2014-08-05 22:27:01

标签: scala

阅读这篇文章关于Scala http://josephmoniz.github.io/blog/2013/04/04/scala-reduce-vs-fold/中的reduce vs fold,它指出"你正在取一些N的值并对它执行聚合操作,使得最终结果通常是某个值< = N "

但是这个陈述是错误的,因为对N个值进行求和会产生一个值> = N?

更新:我认为< =在这种情况下意味着相同的类型或子类型

4 个答案:

答案 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)

见答案:

difference between foldLeft and reduceLeft in Scala

reduce和fold是reduceLeft和foldLeft

的快捷方式