Scala如何按对象内置列表的单个元素对对象列表进行分组?
实现方案
核心思路是先对集合做*扁平映射(flatMap)*展开每个对象关联的全部分类,再执行分组操作,全程使用不可变集合,无显式循环。
针对Car case类的完整实现
你需要先处理两个Option字段的边界情况,过滤掉分类为空、油箱容量为空的无效数据后再展开分类,代码如下:
// 示例输入数据集 val carList: List[Car] = ??? val categoryFuelMap: Map[String, List[Int]] = carList // 过滤无效数据:分类为空/油箱容量为空的车辆不参与统计 .filter(car => car.category.isDefined && car.fuelCapacity.isDefined) // 扁平展开:关联N个分类的车辆会生成N条 (分类名, 油箱容量) 二元组 .flatMap(car => car.category.get.map(cateName => cateName -> car.fuelCapacity.get) ) // 按分类名分组,提取对应分类下所有油箱容量的列表 .groupMap(_._1)(_._2)
如果你使用的Scala版本低于2.13,没有内置groupMap方法,可以替换为如下写法:
.groupBy(_._1).mapValues(_.map(_._2))
后续统计示例(计算单分类平均油箱容量)
拿到上述生成的categoryFuelMap后,可以直接完成统计需求:
val categoryAvgFuel: Map[String, Double] = categoryFuelMap.view .filter(_._2.nonEmpty) // 过滤无有效数据的分类 .mapValues(capacities => capacities.sum.toDouble / capacities.size) .toMap
原理解释
- 用
flatMap替代map是为了把单车辆生成的List[(String, Int)]自动扁平为一级二元组列表,避免出现嵌套集合 - 全程操作均返回不可变的新集合,无任何可变变量、显式循环逻辑
- 边界过滤规则可以根据业务需求调整,如需保留分类为空的车辆,可以单独映射为一个自定义的默认分类键
内容的提问来源于stack exchange,提问作者whaddaplaya
相关产品推荐
相关产品推荐

