Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么scala reduce()和reduceLeft()以相同的方式减少值序列?_Scala_Collections - Fatal编程技术网

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

为什么scala reduce()和reduceLeft()以相同的方式减少值序列?,scala,collections,Scala,Collections,如果我跑步: List(1, 4, 3, 9).reduce {(a, b) => println(s"$a + $b"); a + b} 结果是: 1 + 4 5 + 3 8 + 9 但是,如果我使用reduceLeft而不是reduce,它还会打印: 1 + 4 5 + 3 8 + 9 我认为reduce以这种方式减少了值的顺序: (1+4) + (3+9) (5) + (12) (17) reduceLeft和reduce之间的真正区别是什么?区别在于:

如果我跑步:

List(1, 4, 3, 9).reduce {(a, b) => println(s"$a + $b"); a + b}
结果是:

1 + 4
5 + 3
8 + 9
但是,如果我使用
reduceLeft
而不是
reduce
,它还会打印:

1 + 4
5 + 3
8 + 9
我认为
reduce
以这种方式减少了值的顺序:

(1+4) + (3+9)
(5) + (12)
(17)
reduceLeft
reduce
之间的真正区别是什么?

区别在于:

  • reduce
    可以按任意顺序进行reduce;对于
    列表
    而言,它恰好与
    reduceLeft
    相同,因为它更高效(因此,它们中的大多数都是相同的)。对于另一个集合,它可能相当于
    reduceRight
    ,对于树类型,它可能更符合您的预期

  • 不同类型的签名:

    reduce[B >: A](op: (B, B) => B): B
    

    reduceLeft[B >: A](op: (B, A) => B): B
    
    因为
    reduceLeft
    op
    的第一个参数始终是调用它的集合的元素,但是对于
    reduce
    来说,它可能是递归
    reduce
    调用的结果


  • 看看这两个函数的类型:

    def reduce[B >: A](op: (B, B) => B): B 
    def reduceLeft[B >: A](op: (B, A) => B): B
    
    请注意,
    reduceLeft
    op
    的第二个参数是
    A
    (与元素类型相同),而在
    reduce
    中是
    B
    (与返回值相同)

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

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

    另一方面,
    reduceLeft
    只能按顺序工作(顾名思义,从左到右),操作不必是关联的,并且可以期望其第二个参数始终是序列的一个元素(第一个参数是迄今为止操作的结果)

    考虑

        val sum = (1 to 100).reduce(_ + _) 
    
    这将产生与
    (1到100)相同的结果。reduceLeft(+u-)
    ,只是前者可以并行化。 另一方面:

        val strings = (1 to 100).reduceLeft[Any](_.toString + ";" + _.toString) 
    
    不应写为
    reduce
    (即使在这个人为的示例中,只要您坚持串行处理,它就可以,甚至可以工作),因为结果取决于元素输入操作的顺序。

    “我认为reduce以这种方式减少了值的顺序:”ham no.
    reduce
    的大多数实现只是回退到
    reduceLeft
    ,但它们可能回退到
    reduceRight
    -
    reduce
    只是不能保证操作的顺序,如果您不关心订单,请使用
    reduce
    ,因为基础集合将选择最有效的订单,如果您需要从左到右或从右到左选择其他订单之一;区别更多的是语义,而不是真正的实现细节。如果您想要总是并行搜索的内容,请搜索
    aggregate