foldLeft与foldRight是特质TraversableOnce定义的高阶函数,直译过来为向左折叠和向右折叠。具体实现如下摘出的代码所示:
trait TraversableOnce[+A] extends Any with GenTraversableOnce[A] {
@deprecated("Use foldLeft instead of /:", "2.12.10")
def /:[B](z: B)(op: (B, A) => B): B = foldLeft(z)(op)
@deprecated("Use foldRight instead of :\\", "2.12.10")
def :\[B](z: B)(op: (A, B) => B): B = foldRight(z)(op)
// 泛型为B,第一个参数z为B类型对象(初始值),第二个参数为返回类型为B的函数
def foldLeft[B](z: B)(op: (B, A) => B): B = {
// 初始值z赋值为result变量
var result = z
// 遍历当前类对象集合,将result变量与集合取出的每个对象作为参数传递给op函数,
// 每迭代一次op函数的返回值都赋给result变量
this foreach (x => result = op(result, x))
// 最终获取result作为返回值
result
}
// 从后往前遍历集合,初次结果为z,然后把遍历对象和上次结果传给函数,如此迭代下去直到集合遍历完毕。
def foldRight[B](z: B)(op: (A, B) => B): B =
reversed.foldLeft(z)((x, y) => op(y, x))
protected[this] def reversed = {
var elems: List[A] = Nil
self foreach (elems ::= _)
elems
}
}
foldLeft
通过不断迭代来得到结果的过程,首先把第一个参数作为结果,然后从开始遍历集合,上次结果与本次遍历的对象作为参数传递给第二个参数代表的函数,得到的结果与再次遍历的对象再次作为参数传递给函数,如此一直迭代下去,集合遍历结束 后的结果就是最终返回的结果。
举例来看:
val seq = Seq(1,2,3)
seq.foldLeft(0)(_-_)
运行步骤:
① 初始值 0 - 遍历集合第一个值 1 = 结果 -1
② 上步结果 1 - 遍历集合第二个值 2 = 结果 -3
③ 上步结果 3 - 遍历集合第三个值 3 = 结果 -6
/: 是 foldLeft 的另一只写法,从scala版本2.12.10开始被弃用了,可能在老代码里遇到。
val seq = Seq(1,2,3)
(0/:seq)(_-_)
foldRight
对集合从后往前遍历,首先把第一个参数作为结果,然后把本次遍历的对象与上次结果作为参数传递给第二个参数代表的函数,得到的结果后,再重复上述步骤直到集合遍历结束,遍历结束后的结果就是最终返回的结果。
举例来看:
val seq = Seq(1,2,3)
seq.foldRight(0)(_-_)
运行步骤:
① 先反转集合的到 Seq(3,2,1)
① 遍历集合第一个值 3 - 初始值 0 = 结果 3
② 遍历集合第二个值 2 - 上步结果 3 = 结果 -1
③ 遍历集合第三个值 1 - 上步结果 -1= 结果 2
:\ 是 foldRight 的另一只写法,从scala版本2.12.10开始被弃用了。
val seq = Seq(1,2,3)
(seq:\0)(_-_)
foldRight理解起来要绕一些,可以多找几个例子练习,加深理解。