Scala的foldLeft与foldRight详解

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)(_-_)

运行步骤:
① res1 = f(0,1) => 0 - 1 == -1 【 初始值 0 - 遍历集合第一个值 1 = 结果 -1 】
② res2 = f(-1,2) => -1 - 2 == -3 【 上步结果 -1 - 遍历集合第二个值 2 = 结果 -3】
③ res3 = f(-3,3) => -3 - 3 == -6 【 上步结果 -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)
① res1 = f(3,0) => 3 - 0 == 3 【遍历集合第一个值 3 - 初始值 0 = 结果 3 】
② res2 = f(2,3) => 2 - 3 == -1 【遍历集合第二个值 2 - 上步结果 3 = 结果 -1】
③ res3 = f(1,-1) => 1 - (-1) == 2 【遍历集合第三个值 1 - 上步结果 -1= 结果 2】
在这里插入图片描述

:\ 是 foldRight 的另一只写法,从scala版本2.12.10开始被弃用了。

val seq = Seq(1,2,3)
(seq:\0)(_-_)

在这里插入图片描述
foldRight理解起来要绕一些,可以多找几个例子练习,加深理解。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值