- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
为什么Scala和Spark、Scalding等框架都有reduce
和 foldLeft
?那么reduce
和有什么区别?和 fold
?
最佳答案
减少与左折叠
在与此主题相关的任何其他 stackoverflow 答案中都没有提到的一个很大的区别是 reduce
应该给定一个可交换的幺半群,即一个既可交换又可结合的运算。这意味着操作可以并行化。
这种区别对于大数据/MPP/分布式计算非常重要,这也是为什么reduce
的全部原因。甚至存在。收藏可以切碎和reduce
可以对每个chunk进行操作,那么reduce
可以对每个块的结果进行操作——事实上,分块的级别不需要停止一层深。我们也可以切碎每一块。这就是为什么在给定无限数量的 CPU 的情况下,对列表中的整数求和是 O(log N) 的原因。
如果你只看签名,就没有理由 reduce
存在是因为你可以用 reduce
实现你能做的一切与 foldLeft
. foldLeft
的功能大于 reduce
的功能.
但是你不能并行化 foldLeft
,所以它的运行时间总是 O(N)(即使你输入一个可交换的幺半群)。这是因为假设操作不是可交换的幺半群,因此累积值将由一系列顺序聚合计算。foldLeft
不假设交换性或结合性。关联性提供了拆分集合的能力,而交换性使累积变得容易,因为顺序并不重要(因此聚合每个块的每个结果的顺序并不重要)。严格来说,交换性不是并行化所必需的,例如分布式排序算法,它只是使逻辑更容易,因为您不需要给块排序。
如果您查看 reduce
的 Spark 文档它特别说“......交换和结合二元运算符”
http://spark.apache.org/docs/1.0.0/api/scala/index.html#org.apache.spark.rdd.RDD
这是证明reduce
不仅仅是 foldLeft
的特例
scala> val intParList: ParSeq[Int] = (1 to 100000).map(_ => scala.util.Random.nextInt()).par
scala> timeMany(1000, intParList.reduce(_ + _))
Took 462.395867 milli seconds
scala> timeMany(1000, intParList.foldLeft(0)(_ + _))
Took 2589.363031 milli seconds
fold
Scalding 中的方法,因为在(严格的)Map Reduce 编程模型下我们无法定义
fold
因为块没有排序和
fold
只需要结合性,不需要交换性。
reduce
无需累积顺序即可工作,
fold
需要一个累积顺序,正是这个累积顺序需要一个零值,而不是零值的存在区分它们。严格来说
reduce
应该在一个空集合上工作,因为它的零值可以通过取任意值
x
推导出来。然后解决
x op y = x
,但这不适用于非交换运算,因为可能存在不同的左右零值(即
x op y != y op x
)。当然,Scala 不会费心算出这个零值是什么,因为这需要做一些数学运算(这可能是无法计算的),所以只是抛出一个异常。
reduce
已成为
fold
的代名词,而不是保留它在 MapReduce 中的原始含义。现在这些术语经常互换使用,并且在大多数实现中表现相同(忽略空集合)。怪异性会因特殊性而加剧,就像在 Spark 中一样,我们现在将解决这些问题。
fold
,但是子结果(每个分区一个)的组合顺序(在撰写本文时)与任务完成的顺序相同 - 因此是不确定的。感谢@CafeFeed 指出
fold
用途
runJob
,在阅读代码后,我意识到它是不确定的。 Spark 的
treeReduce
造成了进一步的困惑。但没有
treeFold
.
reduce
之间有区别和
fold
即使应用于非空序列。前者被定义为 MapReduce 编程范式的一部分,用于具有任意顺序的集合 (
http://theory.stanford.edu/~sergei/papers/soda10-mrc.pdf ),并且除了给出确定性结果的关联性之外,还应该假设运算符是可交换的。后者是根据原形定义的,并且要求集合具有序列的概念(或递归定义,如链表),因此不需要可交换运算符。
reduce
和
fold
倾向于以相同的方式运行,无论是正确的(如在 Scala 中)还是错误的(如在 Spark 中)。
fold
可以避免混淆。在 Spark 中完全丢弃。至少 spark 在他们的文档中有一个注释:
This behaves somewhat differently from fold operations implemented for non-distributed collections in functional languages like Scala.
关于scala - 函数式编程(尤其是 Scala 和 Scala API)中的 reduce 和 foldLeft/fold 之间的区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25158780/
假设我们有 Seq val ourSeq = Seq(10,5,3,5,4)。 我想返回一个新的列表,它从左边读取并在看到重复的数字时停止(例如 Seq(10,5,3) 因为 5 是重复的)。 我正在
如何在 Scala 中模拟以下行为?即在满足蓄能器的某些特定条件时继续折叠。 def foldLeftWhile[B](z: B, p: B => Boolean)(op: (B, A) => B):
我目前正在学习 Scala,但还有很多我不明白的东西...... 所以,当出现一个疯狂的答案时,我正在随机浏览一些堆栈溢出:https://stackoverflow.com/a/19093282/3
我有以下代码片段: import scala.io.Source object test extends App { val lineIterator = Source.fromFile("tes
在我的代码中,我有以下内容: type Occurrences = List[(Char, Int)] def subtract(x: Occurrences, y: Occurrences)
我正在尝试使用 Shapeless 中的 HList。 这是我的第一次尝试: trait Column[T] { val name: String } case class CV[T](co
我有这样的 Scala 代码 var i = 1 for(e (i+1)*array(i)).sum (或者稍微快一点,因为您可以随时创建中间体: array.indices.iterator.ma
所以在阅读中this question有人指出,不是程序代码: def expand(exp: String, replacements: Traversable[(String, String)])
我有一个 spark 数据框,我想使用 foldLeft(或任何其他方法)将聚合函数应用于每一列。应用于列的聚合函数将取决于列的数据类型。 请注意,由于我将使用大型数据框,因此我不想使用 .colle
我有一个包含 1 和 -1 的列表。我追求的目标是在总数为 -1 时找到 List 中的位置。 List[Int] = List(1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -
当我省略点符号来应用 foldLeft 时,谁能解释为什么我看到以下编译错误功能?(2.9.2版) scala> val l = List(1, 2, 3) res19: List[Int] = Li
我有一个 List定义为: val l = List("1", "2", "3") 我想把它转换成字符串 "1:2:3" 一种方法如下: l.foldLeft("")((x, y) => x + (i
你如何使用 Map.foldLeft?根据docs看起来像 foldLeft [B] (z: B)(op: (B, (A, B)) ⇒ B) : B 但我有困难: Map("first"->1,"se
我试图了解fold和foldLeft以及各自的reduce和reduceLeft如何工作。我使用 Fold 和 FoldLeft 作为示例 scala> val r = List((ArrayBuff
好吧,我认为这很容易,尝试练习 Scala 的集合运算符,我的示例是一个点列表。 该类可以计算并返回到另一点的距离( double )。 但是,向左折叠似乎不是正确的解决方案 - 考虑元素 e1、e2
谁能解释为什么我在应用 foldLeft 函数时省略点符号时会看到以下编译错误?(版本 2.9.2) scala> val l = List(1, 2, 3) res19: List[Int] = L
这是来自 Coursera 的类(class),直到现在还没有人能帮助我。以下作品,摘自一次讲座。 object polynomials { class Poly(terms0: Map[Int,
在这段代码中,我试图对两个 Strings 的 xor 值求和: val s1 = "1c0111001f010100061a024b53535009181c"; val s2 = "68697420
使用 foldRight 定义如下 concat 函数可以正确 concat list def concat[T](xs: List[T], ys: List[T]): List[T] = (xs f
在一个在线类(class)中,有人说 foldLeft和 foldRight等效于 的运算符结合和交换 . 其中一名学生坚持认为此类运算符只需要具有关联性。所以这个属性对于函数组合和矩阵乘法等操作应该
我是一名优秀的程序员,十分优秀!