Scala中foldLeft和reduceLeft之间的区别

Raj*_*tty 191 functional-programming scala fold higher-order-functions

我已经学会了foldLeft和之间的基本区别reduceLeft

foldLeft:

  • 初始值必须通过

reduceLeft:

  • 将集合的第一个元素作为初始值
  • 如果集合为空,则抛出异常

还有其他区别吗?

有两种方法具有相似功能的任何特定原因?

agi*_*eel 295

在给出实际答案之前,这里很少提及:

  • 你的问题没有任何关系left,而是减少和折叠之间的区别
  • 差别不是实现,只需看一下签名即可.
  • 问题与Scala没有任何关系,而是与函数式编程的两个概念有关.

回到你的问题:

这是签名foldLeft(也可能是foldRight我要做的):

def foldLeft [B] (z: B)(f: (B, A) => B): B
Run Code Online (Sandbox Code Playgroud)

这里是签名reduceLeft(这里的方向无关紧要)

def reduceLeft [B >: A] (f: (B, A) => B): B
Run Code Online (Sandbox Code Playgroud)

这两个看起来非常相似,从而引起了混乱.reduceLeft是一种特殊情况foldLeft(顺便说一下,你有时可以通过使用其中任何一种来表达同样的事情).

当你对它调用reduceLeftsay时,List[Int]它会将整个整数列表减少为单个值,这将是类型Int(或者是超类型Int,因此[B >: A]).

当你打电话foldLeftList[Int]它时,它会将整个列表(想象滚动一张纸)折叠成一个值,但这个值不必与Int(因此[B])相关.

这是一个例子:

def listWithSum(numbers: List[Int]) = numbers.foldLeft((List.empty[Int], 0)) {
   (resultingTuple, currentInteger) =>
      (currentInteger :: resultingTuple._1, currentInteger + resultingTuple._2)
}
Run Code Online (Sandbox Code Playgroud)

此方法采用a List[Int]并返回a Tuple2[List[Int], Int](List[Int], Int).它计算总和并返回一个带有整数列表的元组,它的总和.顺便说一下,列表是向后返回的,因为我们使用的是foldLeft代替foldRight.

观看One Fold以统治所有人以获得更深入的解释.


Kim*_*bel 189

reduceLeft只是一种方便的方法.它相当于

list.tail.foldLeft(list.head)(_)
Run Code Online (Sandbox Code Playgroud)

  • 好,简洁的答案:)虽然可能想要纠正`reducelft`的拼写 (11认同)
  • 好答案.这也突出了为什么`fold`在空列表上工作,而`reduce`没有. (10认同)

tho*_*dge 44

foldLeft更通用,您可以使用它来生成与您最初放入的内容完全不同的内容.而reduceLeft只能生成相同类型或超类型集合类型的最终结果.例如:

List(1,3,5).foldLeft(0) { _ + _ }
List(1,3,5).foldLeft(List[String]()) { (a, b) => b.toString :: a }
Run Code Online (Sandbox Code Playgroud)

foldLeft将应用与最后折叠结果闭合(使用初始值第一次)和下一个值.

reduceLeft另一方面,将首先组合列表中的两个值并将其应用于闭包.接下来,它将其余值与累积结果组合在一起.看到:

List(1,3,5).reduceLeft { (a, b) => println("a " + a + ", b " + b); a + b }
Run Code Online (Sandbox Code Playgroud)

如果列表为空,则foldLeft可以将初始值显示为合法结果.reduceLeft另一方面,如果在列表中找不到至少一个值,则没有合法值.


Ale*_*nov 5

它们都在Scala标准库中的基本原因可能是因为它们都在Haskell标准库中(称为foldlfoldl1).如果reduceLeft不是,它通常被定义为不同项目中的便利方法.


小智 5

作为参考,reduceLeft如果应用于具有以下错误的空容器,则会出错.

java.lang.UnsupportedOperationException: empty.reduceLeft
Run Code Online (Sandbox Code Playgroud)

重新编写要使用的代码

myList foldLeft(List[String]()) {(a,b) => a+b}
Run Code Online (Sandbox Code Playgroud)

是一个潜在的选择.另一种方法是使用reduceLeftOption返回Option包装结果的variant.

myList reduceLeftOption {(a,b) => a+b} match {
  case None    => // handle no result as necessary
  case Some(v) => println(v)
}
Run Code Online (Sandbox Code Playgroud)