我已经了解了foldLeft和reducleft的基本区别
foldLeft:
必须传递初始值
reduceLeft:
以集合的第一个元素作为初始值 如果集合为空,则抛出异常
还有其他区别吗?
有什么特殊的原因要有两个功能相似的方法吗?
我已经了解了foldLeft和reducleft的基本区别
foldLeft:
必须传递初始值
reduceLeft:
以集合的第一个元素作为初始值 如果集合为空,则抛出异常
还有其他区别吗?
有什么特殊的原因要有两个功能相似的方法吗?
当前回答
规模2.13.3,演示:
val names = List("Foo", "Bar")
println("ReduceLeft: "+ names.reduceLeft(_+_))
println("ReduceRight: "+ names.reduceRight(_+_))
println("Fold: "+ names.fold("Other")(_+_))
println("FoldLeft: "+ names.foldLeft("Other")(_+_))
println("FoldRight: "+ names.foldRight("Other")(_+_))
输出:
ReduceLeft: FooBar
ReduceRight: FooBar
Fold: OtherFooBar
FoldLeft: OtherFooBar
FoldRight: FooBarOther
其他回答
它们都在Scala标准库中的基本原因可能是因为它们都在Haskell标准库中(称为foldl和foldl1)。如果reducleft不是,那么在不同的项目中,它通常被定义为一个方便的方法。
《Scala函数式编程原则》(Martin Odersky):
函数reduceLeft是根据一个更通用的函数foldLeft定义的。 foldLeft类似于reduceLeft,但接受累加器z作为附加参数,当在空列表上调用foldLeft时返回: (List (x1,…, xn) foldLeft z)(op) =(…(z op x1) op…)op x
[与reducleft相反,它会在空列表上调用时抛出异常。]
本课程(见第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)
}
}
注意,foldLeft返回一个U类型的值,它不一定与List[T]的类型相同,但reducelefleft返回一个与List相同类型的值)。
foldLeft是更通用的,你可以用它来产生一些完全不同于你最初输入的东西。而reduceLeft只能产生与集合类型相同类型或超类型的最终结果。例如:
List(1,3,5).foldLeft(0) { _ + _ }
List(1,3,5).foldLeft(List[String]()) { (a, b) => b.toString :: a }
foldLeft将应用带有上次折叠结果(第一次使用初始值)和下一个值的闭包。
另一方面,reducleft将首先组合列表中的两个值,并将它们应用到闭包中。接下来,它将把剩余的值与累积结果结合起来。看到的:
List(1,3,5).reduceLeft { (a, b) => println("a " + a + ", b " + b); a + b }
如果列表为空,则foldLeft可以将初始值表示为合法结果。另一方面,如果reducleft在列表中找不到至少一个值,那么它就没有合法的值。
规模2.13.3,演示:
val names = List("Foo", "Bar")
println("ReduceLeft: "+ names.reduceLeft(_+_))
println("ReduceRight: "+ names.reduceRight(_+_))
println("Fold: "+ names.fold("Other")(_+_))
println("FoldLeft: "+ names.foldLeft("Other")(_+_))
println("FoldRight: "+ names.foldRight("Other")(_+_))
输出:
ReduceLeft: FooBar
ReduceRight: FooBar
Fold: OtherFooBar
FoldLeft: OtherFooBar
FoldRight: FooBarOther
为了真正理解折叠/缩减的作用, 检查这个:http://wiki.tcl.tk/17983 非常好的解释。一旦你掌握了折叠的概念, Reduce会和上面的答案一起出现: list.tail.foldLeft (list.head) (_)