You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scala中reduceLeft与reduceRight的概念疑问及实现求助

关于Scala reduceLeft与reduceRight的疑惑解答

一、执行逻辑的解惑

你对执行逻辑的判断是正确的:对列表[1,2,3]执行加法得到1 + sum(2,3),这确实是reduceRight的执行逻辑,而非reduceLeft。

两者的核心区别在于结合方向:

  • reduceLeft是从左到右依次结合,先计算最左边的两个元素,再将结果与下一个元素运算。对于[1,2,3]的加法,执行顺序是((1+2)+3),对应你说的sum(1,2)+3。
  • reduceRight是从右到左结合,先计算最右边的子列表,再将头部元素与子列表的运算结果结合。对于[1,2,3]的加法,执行顺序是(1+(2+3)),也就是你看到的1 + sum(2,3)。

因为加法满足交换律和结合律,所以两种方式结果相同,但如果换成不满足结合律的操作(比如减法),结果会完全不同:

  • List(1,2,3).reduceLeft(_ - _) → (1-2)-3 = -4
  • List(1,2,3).reduceRight(_ - _) → 1-(2-3) = 2

所以你遇到的课件标注错误的概率很高,你的判断没问题。

二、用case语句实现reduceLeft的指导

先看课件里用case实现reduceRight的典型写法(递归模式匹配):

def reduceRight[T](list: List[T])(op: (T, T) => T): T = list match {
  case head :: Nil => head
  case head :: tail => op(head, reduceRight(tail)(op))
}

reduceLeft的递归实现需要从左累积结果,直接用模式匹配的话,需要借助辅助函数维护累积值(每次拿当前累积结果和下一个元素运算),具体实现如下:

def reduceLeft[T](list: List[T])(op: (T, T) => T): T = {
  // 辅助递归函数:acc是当前累积值,remaining是剩余未处理的列表
  def loop(acc: T, remaining: List[T]): T = remaining match {
    case Nil => acc // 剩余列表为空,返回累积值
    case next :: tail => loop(op(acc, next), tail) // 更新累积值并继续递归
  }

  list match {
    case Nil => throw new UnsupportedOperationException("reduceLeft cannot be called on empty list")
    case head :: tail => loop(head, tail) // 初始累积值为列表首元素,启动递归
  }
}

如果不想用辅助函数,也可以用模式匹配直接处理多元素场景(可读性稍弱):

def reduceLeft[T](list: List[T])(op: (T, T) => T): T = list match {
  case Nil => throw new UnsupportedOperationException("reduceLeft on empty list")
  case head :: Nil => head
  case head :: next :: tail => reduceLeft(op(head, next) :: tail)(op)
}

测试减法场景验证:

val nums = List(1,2,3)
reduceLeft(nums)(_ - _) // 输出-4,符合reduceLeft的预期

内容的提问来源于stack exchange,提问作者figs_and_nuts

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 21:33:09