Scala 中 foldLeft 和 reduceLeft 的区别
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7764197/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
difference between foldLeft and reduceLeft in Scala
提问by Rajesh Pitty
I have learned the basic difference between foldLeftand reduceLeft
我已经了解了foldLeft和之间的基本区别reduceLeft
foldLeft:
折叠左:
- initial value has to be passed
- 必须传递初始值
reduceLeft:
减少左:
- takes first element of the collection as initial value
- throws exception if collection is empty
- 将集合的第一个元素作为初始值
- 如果集合为空则抛出异常
Is there any other difference ?
还有其他区别吗?
Any specific reason to have two methods with similar functionality?
有两种具有类似功能的方法的任何具体原因?
回答by agilesteel
Few things to mention here, before giving the actual answer:
在给出实际答案之前,这里有几件事要提:
- Your question doesn't have anything to do with
left, it's rather about the difference between reducing and folding - The difference is not the implementation at all, just look at the signatures.
- The question doesn't have anything to do with Scala in particular, it's rather about the two concepts of functional programming.
- 您的问题与 无关
left,而是关于减少和折叠之间的区别 - 区别根本不在于实现,只看签名。
- 这个问题与 Scala 没有任何关系,而是关于函数式编程的两个概念。
Back to your question:
回到你的问题:
Here is the signature of foldLeft(could also have been foldRightfor the point I'm going to make):
这是foldLeft(也可能是foldRight我要提出的观点)的签名:
def foldLeft [B] (z: B)(f: (B, A) => B): B
And here is the signature of reduceLeft(again the direction doesn't matter here)
这是reduceLeft(这里的方向再次无关紧要)的签名
def reduceLeft [B >: A] (f: (B, A) => B): B
These two look very similar and thus caused the confusion. reduceLeftis a special case of foldLeft(which by the way means that you sometimescan express the same thing by using either of them).
这两个看起来非常相似,因此引起了混乱。reduceLeft是foldLeft( 顺便说一句,这意味着您有时可以通过使用它们中的任何一个来表达相同的事情) 的特殊情况。
When you call reduceLeftsay on a List[Int]it will literally reduce the whole list of integers into a single value, which is going to be of type Int(or a supertype of Int, hence [B >: A]).
当您reduceLeft在 a 上调用say 时,List[Int]它实际上会将整个整数列表减少为单个值,该值将是类型Int(或 的超类型Int,因此是[B >: A])。
When you call foldLeftsay on a List[Int]it will fold the whole list (imagine rolling a piece of paper) into a single value, but this value doesn't have to be even related to Int(hence [B]).
当您foldLeft在 a 上调用say 时,List[Int]它会将整个列表(想象一下滚动一张纸)折叠成一个值,但该值甚至不必与Int(因此[B])相关。
Here is an example:
下面是一个例子:
def listWithSum(numbers: List[Int]) = numbers.foldLeft((List.empty[Int], 0)) {
(resultingTuple, currentInteger) =>
(currentInteger :: resultingTuple._1, currentInteger + resultingTuple._2)
}
This method takes a List[Int]and returns a Tuple2[List[Int], Int]or (List[Int], Int). It calculates the sum and returns a tuple with a list of integers and it's sum. By the way the list is returned backwards, because we used foldLeftinstead of foldRight.
此方法采用 aList[Int]并返回 a Tuple2[List[Int], Int]or (List[Int], Int)。它计算总和并返回一个包含整数列表的元组,它是总和。顺便说一下,列表是向后返回的,因为我们使用了foldLeft代替foldRight。
Watch One Fold to rule them allfor a more in depth explanation.
观看One Fold 统治它们以获得更深入的解释。
回答by Kim Stebel
reduceLeftis just a convenience method. It is equivalent to
reduceLeft只是一种方便的方法。它相当于
list.tail.foldLeft(list.head)(_)
回答by thoredge
foldLeftis more generic, you can use it to produce something completely different than what you originally put in. Whereas reduceLeftcan only produce an end result of the same type or super type of the collection type. For example:
foldLeft更通用,您可以使用它来产生与您最初放入的完全不同的东西。而reduceLeft只能产生与集合类型相同类型或超类型的最终结果。例如:
List(1,3,5).foldLeft(0) { _ + _ }
List(1,3,5).foldLeft(List[String]()) { (a, b) => b.toString :: a }
The foldLeftwill apply the closure with the last folded result (first time using initial value) and the next value.
在foldLeft将应用与最后折叠结果闭合(使用初始值第一次)和下一个值。
reduceLefton the other hand will first combine two values from the list and apply those to the closure. Next it will combine the rest of the values with the cumulative result. See:
reduceLeft另一方面,将首先组合列表中的两个值并将它们应用于闭包。接下来,它将剩余的值与累积结果相结合。看:
List(1,3,5).reduceLeft { (a, b) => println("a " + a + ", b " + b); a + b }
If the list is empty foldLeftcan present the initial value as a legal result. reduceLefton the other hand does not have a legal value if it can't find at least one value in the list.
如果列表为空,则foldLeft可以将初始值作为合法结果呈现。reduceLeft另一方面,如果在列表中找不到至少一个值,则它没有合法值。
回答by Alexey Romanov
The basic reason they are both in Scala standard library is probably because they are both in Haskell standard library (called foldland foldl1). If reduceLeftwasn't, it would quite often be defined as a convenience method in different projects.
它们都在 Scala 标准库中的基本原因可能是因为它们都在 Haskell 标准库中(称为foldl和foldl1)。如果reduceLeft不是,它通常会被定义为不同项目中的一种便利方法。
回答by Martin Smith
For reference, reduceLeftwill error if applied to an empty container with the following error.
作为参考,reduceLeft如果应用于空容器,则会出现以下错误。
java.lang.UnsupportedOperationException: empty.reduceLeft
Reworking the code to use
重新编写要使用的代码
myList foldLeft(List[String]()) {(a,b) => a+b}
is one potential option. Another is to use the reduceLeftOptionvariant which returns an Option wrapped result.
是一种潜在的选择。另一种方法是使用reduceLeftOption返回 Option 包装结果的变体。
myList reduceLeftOption {(a,b) => a+b} match {
case None => // handle no result as necessary
case Some(v) => println(v)
}
回答by C8H10N4O2
From Functional Programming Principles in Scala(Martin Odersky):
来自Scala 中的函数式编程原则(Martin Odersky):
The function
reduceLeftis defined in terms of a more general function,foldLeft.
foldLeftis likereduceLeftbut takes an accumulatorz, as an additional parameter, which is returned whenfoldLeftis called on an empty list:
(List (x1, ..., xn) foldLeft z)(op) = (...(z op x1) op ...) op x
该函数
reduceLeft是根据更一般的函数 定义的foldLeft。
foldLeft就像reduceLeft但需要一个accumulatorz作为附加参数,当foldLeft在空列表上调用时返回:
(List (x1, ..., xn) foldLeft z)(op) = (...(z op x1) op ...) op x
[as opposed to reduceLeft, which throws an exception when called on an empty list.]
[与reduceLeft在空列表上调用时抛出异常的 不同。]
The course (see lecture 5.5) provides abstract definitions of these functions, which illustrates their differences, although they are very similar in their use of pattern matching and recursion.
本课程(见第 5.5 课)提供了这些函数的抽象定义,说明了它们的区别,尽管它们在模式匹配和递归的使用上非常相似。
abstract class List[T] { ...
def reduceLeft(op: (T,T)=>T) : T = this match{
case Nil => throw new Error("Nil.reduceLeft")
case x :: xs => (xs foldLeft x)(op)
}
def foldLeft[U](z: U)(op: (U,T)=>U): U = this match{
case Nil => z
case x :: xs => (xs foldLeft op(z, x))(op)
}
}
Note that foldLeftreturns a value of type U, which is not necessarily the same type as List[T], but reduceLeft returns a value of the same type as the list).
请注意,foldLeft返回一个 type 的值U,该值不一定与 相同List[T],但 reduceLeft 返回一个与列表相同类型的值)。
回答by Henry H.
To really understand what are you doing with fold/reduce, check this: http://wiki.tcl.tk/17983very good explanation. once you get the concept of fold, reduce will come together with the answer above: list.tail.foldLeft(list.head)(_)
要真正了解您使用 fold/reduce 做什么,请查看:http: //wiki.tcl.tk/17983非常好的解释。一旦你理解了折叠的概念,reduce 就会和上面的答案一起出现:list.tail.foldLeft(list.head)(_)

