scala 减少和折叠的区别

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25149359/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 06:28:57  来源:igfitidea点击:

Difference between reduce and fold

scala

提问by blue-sky

Reading this article about reduce vs fold in Scala http://josephmoniz.github.io/blog/2013/04/04/scala-reduce-vs-fold/it states "you are taking some value of N and performing aggregation operations on it such that the end result is typically some value of <= N."

阅读这篇关于 Scala 中减少与折叠的文章http://josephmoniz.github.io/blog/2013/04/04/scala-reduce-vs-fold/它指出“你正在取 N 的一些值并在它使得最终结果通常是 <= N 的某个值。”

But is this statement false since summing over N values produces a value >= N ?

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

Update : I think <= in this case means same type or sub-type

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

回答by Rex Kerr

I think it's a flawed characterization. It's better to think of fold like this:

我认为这是一个有缺陷的表征。最好这样考虑折叠:

In:
  initial value
  way to combine stuff with initial value
  collection
Out:
  combined stuff

And reduce is like this:

而reduce是这样的:

In:
  way to combine stuff
  collection
Out:
  combined stuff

That is, the difference is whether you have an initial value (which might not even be of the same type as what you've got in the collection!), as fold does, or whether you just collapse the values you already have, as reduce does.

也就是说,不同之处在于您是否有一个初始值(它甚至可能与您在集合中的类型不同!),就像 fold 一样,或者您是否只是折叠您已经拥有的值,如减少确实。

If you have a natural zero, that is, something that can be combined without changing what it combines with, then you can implement reduce as a fold starting with a zero. For example, for multiplication the zero is 1(because 1*x == x), so

如果你有一个自然的零,也就是说,可以在不改变它所结合的东西的情况下进行组合,那么你可以将 reduce 实现为从零开始的折叠。例如,对于乘法,零是1(因为1*x == x),所以

List(1,2,3).fold(1){_ * _}
List(1,2,3).reduce{_ * _}

give the same answer. (Only the first gives an answer on an empty list, however!)

给出同样的答案。(但是,只有第一个在空列表中给出答案!)

To see an example of how fold is entirely more general, consider this one--here with a foldLeft so we know to pass the initial value in on the left-hand side of the operation--

要查看 fold 如何更通用的示例,请考虑这个示例——这里有一个 foldLeft,因此我们知道在操作的左侧传递初始值——

List(1,2,3).foldLeft(List(0))((ns,n) => ns ++ List.fill(n+1)(n))

which gives List(0, 1, 1, 2, 2, 2, 3, 3, 3, 3).

这给List(0, 1, 1, 2, 2, 2, 3, 3, 3, 3).

回答by ya_pulser

Fold needs "starting element" be provided, reduce will automatically take 1st element of sequence as starting, so they are kind of equivalent for some degree:

折叠需要提供“起始元素”,reduce 会自动将序列的第一个元素作为起始元素,因此它们在某种程度上是等效的:

val L = List(1,2,3,4)
val H = L.head
val T = L.tail

L.reduce(_+_) ~== T.fold(H)(_+_)

Reduce more compact, but with fold you have ability to provide different start element and change result of the operation, so:

减少更紧凑,但折叠你有能力提供不同的开始元素和改变操作的结果,所以:

2014 + L.reduce(_+_) ~== L.fold(2014)(_+_) // NB: here we use L, not T for fold

Things will be more exciting and more favorable for fold when you will step out of simple arithmetics to some more complex binary operations like Set + Int:

当你从简单的算术跳到一些更复杂的二元运算(如 Set + Int)时,事情会更令人兴奋,也更适合折叠:

List(1,2,3,3,2,2,1).foldLeft(Set[Int]())(_ + _) // will produce Set(1, 2, 3)

... you can fold an JDBC update call :).

...您可以折叠 JDBC 更新调用 :)。

回答by wedens

reduceuses conception called "monoid" to get "zero value" as initializer for accumulator in fold*

reduce使用称为“monoid”的概念来获得“零值”作为折叠中累加器的初始值设定项*

回答by Sergey

see answer here:

在这里看到答案:

difference between foldLeft and reduceLeft in Scala

Scala 中 foldLeft 和 reduceLeft 的区别

reduce and fold are shortcuts for reduceLeft and foldLeft

reduce 和 fold 是 reduceLeft 和 foldLeft 的快捷方式