为什么scala的reduce()和reduceLeft()以同样的方式减少值的序列?

sun*_*cho 7 collections scala

如果我运行:

List(1, 4, 3, 9).reduce {(a, b) => println(s"$a + $b"); a + b}
Run Code Online (Sandbox Code Playgroud)

结果是:

1 + 4
5 + 3
8 + 9
Run Code Online (Sandbox Code Playgroud)

但是,如果我使用reduceLeft而不是reduce,它还会打印:

1 + 4
5 + 3
8 + 9
Run Code Online (Sandbox Code Playgroud)

我认为reduce以这种方式减少值的序列:

(1+4) + (3+9)
(5) + (12)
(17)
Run Code Online (Sandbox Code Playgroud)

reduceLeft和之间的真正区别是什么reduce

Dim*_*ima 14

看一下两个函数的类型:

\n
def reduce[B >: A](op: (B, B) => B): B \ndef reduceLeft[B >: A](op: (B, A) => B): B\n
Run Code Online (Sandbox Code Playgroud)\n

op请注意, in的第二个参数reduceLeftA(与元素类型相同),而 in reduceit 是B(与返回值相同)。

\n

这是一个重要的区别。在reduce中的操作必须是结合的,这意味着您可以将列表拆分为多个段,分别对每个段应用操作,然后再次将其应用于结果以进行组合。

\n

当您想要并行执行操作时,这一点很重要:reduce可以并行应用于列表的不同部分,然后可以组合结果。

\n

reduceLeft另一方面,只能按顺序工作(从左到右,顾名思义),操作不必是关联的,并且可以期望它的第二个参数始终是序列的元素(第一个参数 \xe2\ x80\x93\xc2\xa0 到目前为止的操作结果);

\n

考虑

\n
    val sum = (1 to 100).reduce(_ + _) \n
Run Code Online (Sandbox Code Playgroud)\n

这会产生与 相同的结果(1 to 100).reduceLeft(_ + _),只是前者可以并行化。\n另一方面:

\n
    val strings = (1 to 100).reduceLeft[Any](_.toString + ";" + _.toString) \n
Run Code Online (Sandbox Code Playgroud)\n

不应该写成reduce(尽管在这个人为的示例中,它可以,甚至只要您坚持串行处理就可以工作),因为结果取决于将元素馈送到操作的顺序。

\n