Scala中如何将复杂对象List转换为指定嵌套结构的Map
Scala 实现 List[MyData] 到嵌套Map的转换
实现思路
不用绕复杂的嵌套flatten逻辑,核心分三步:
- 先把每个
MyData实例里的嵌套dataMap拍平,拆成(map键, 来源域名, map值)的最细粒度三元组序列,消除嵌套结构 - 第一次按map的外层key(也就是例子里的key1/key2/key3)分组
- 每个外层key的分组结果内,再按来源域名做第二次分组,把同域名下同key的所有值收集成序列,就得到目标结构
完整实现代码
// 样例类定义 case class MyData( source: String, dataMap: Map[String, String] ) case class LiverampMappingV2( dataMapping: Map[String, Map[String, Seq[String]]] ) // 输入测试数据(修正了原例子里的类名大小写问题,样例类不需要手动new) val data = List( MyData("abc.com", Map("key1" -> "value1", "key2" -> "value2")), MyData("abc.com", Map("key1" -> "value11", "key3" -> "value3")), MyData("pqr.com", Map("key1" -> "value111", "key3" -> "value33")) ) // 核心转换逻辑(全Scala版本通用) val dataMapping: Map[String, Map[String, Seq[String]]] = data .flatMap(item => item.dataMap.map { case (mapKey, value) => (mapKey, item.source, value) }) .groupBy(_._1) .map { case (outerKey, entries) => val innerSourceMap = entries .groupBy(_._2) .map { case (source, sourceEntries) => source -> sourceEntries.map(_._3) } outerKey -> innerSourceMap } // 包装成目标样例类 val target = LiverampMappingV2(dataMapping)
Scala 2.13+ 简化写法
如果使用2.13及以上版本,可以用内置的groupMap方法省略一次map操作,代码更简洁:
val simplifiedMapping = data .flatMap(item => item.dataMap.map { case (k, v) => (k, item.source, v) }) .groupMap(_._1)(entry => (entry._2, entry._3)) .map { case (outerKey, sourceValuePairs) => outerKey -> sourceValuePairs.groupMap(_._1)(_._2) }
结果说明
运行后得到的结果和预期结构完全一致:
Map( key1 -> Map("abc.com" -> List("value1", "value11"), "pqr.com" -> List("value111")), key2 -> Map("abc.com" -> List("value2")), key3 -> Map("abc.com" -> List("value3"), "pqr.com" -> List("value33")) )
注:你给出的预期结果里key3对应abc.com的值写为
value13,对照原始输入属于笔误,实际输出为输入对应的value3。
之前没写对的核心原因是没有先拆分嵌套的dataMap结构,直接对MyData对象做分组的话,没法拿到内部map的key作为外层分组维度,先拆成最细粒度的三元组之后,分组逻辑就非常清晰了。
内容的提问来源于stack exchange,提问作者user3067435
相关产品推荐
相关产品推荐

