【问题标题】:Difference between reduce and fold减少和折叠之间的区别
【发布时间】:2014-08-05 22:27:01
【问题描述】:

阅读这篇关于 Scala http://josephmoniz.github.io/blog/2013/04/04/scala-reduce-vs-fold/ 中的 reduce 与 fold 的文章指出“您正在获取 N 的某个值并对其执行聚合操作,因此最终结果通常是

但是由于对 N 个值求和会产生一个值 >= N,因此该陈述是否错误?

更新:我认为

【问题讨论】:

    标签: scala


    【解决方案1】:

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

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

    而reduce是这样的:

    In:
      way to combine stuff
      collection
    Out:
      combined stuff
    

    也就是说,区别在于您是否有一个初始值(它甚至可能与您在集合中获得的类型不同!),就像 fold 一样,或者您是否只是折叠已经存在的值有,就像 reduce 一样。

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

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

    给出相同的答案。 (然而,只有第一个在空列表上给出答案!)

    要查看 fold 更通用的示例,请考虑这个示例——这里使用 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)

    【讨论】:

      【解决方案2】:

      Fold 需要提供“起始元素”,reduce 会自动将序列的第一个元素作为起始元素,所以它们在某种程度上是等价的:

      val L = List(1,2,3,4)
      val H = L.head
      val T = L.tail
      
      L.reduce(_+_) ~== T.fold(H)(_+_)
      

      reduce 更紧凑,但是使用 fold 你可以提供不同的起始元素并改变操作的结果,所以:

      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 更新调用:)。

      【讨论】:

      • 2014 年的示例具有误导性。 fold 可以多次使用初始值,因此它应该是一个中性元素。
      • 不,fold 不会多次使用初始值,如果你想在同一个集合上的相同操作上等同于 fold 和 reduce,它只需要是一个中性元素,如下所示: L.reduce(_ + _) == L.fold(0)(_ + _)。所以这个例子,2014 + L.reduce(_ + _) ~== L.fold(2014)(_ + _) 并没有真正误导
      【解决方案3】:

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

      【讨论】:

      • 您能否提供文档或示例的链接?谢谢
      【解决方案4】:

      在这里查看答案:

      difference between foldLeft and reduceLeft in Scala

      reduce 和 fold 是 reduceLeft 和 foldLeft 的快捷键

      【讨论】:

      • "reduce 和 fold 是 reduceLeft 和 foldLeft 的快捷方式":不是这样。 reduceLeftfoldLeft 从左到右(从头到尾)应用运算符。 reduceRightfoldRight 从右到左应用它。至于reducefold,顺序是未指定,这允许对其进行并行实现(参见ParIterableLike)。因此,在调用reduce 时,您最好确保您的操作符是关联的,否则结果将不确定。
      猜你喜欢
      • 2012-02-21
      • 2017-11-09
      • 2016-06-28
      • 2011-04-11
      • 1970-01-01
      • 1970-01-01
      • 2014-11-21
      • 2013-12-27
      • 1970-01-01
      相关资源
      最近更新 更多