我有一个Map of Maps数组,想合并相似的键并将它们的值组合到一个列表中。有没有一种优雅的方法来做到这一点,最好不要引入任何新库或更新scala? Scala 2.11.12版
(Map("a" -> Map(1 -> 1.1)),
Map("a" -> Map(2 -> 2.1)),
Map("b" -> Map(1 -> 1.1)),
Map("c" -> Map(1 -> 1.1)),
Map("c" -> Map(2 -> 2.2)))
输出:
Map(
"a" -> List(Map(1 -> 1.1), Map(2 -> 2.1)),
"b" -> List(Map(1 -> 1.1)),
"c" -> List(Map(1 -> 1.1), Map(2 -> 2.2)))
编辑以解释为什么它不是以下内容的重复:Scala: Merge map 该答案不会动态地遍历整个列表并合并相同的键,而只会合并给定的2个特定映射。正如答案所举例说明的那样,真正的解决方案是通过一种优雅的方式遍历列表,不仅合并列表,而且还需要将地图加载到列表中然后进行合并。
答案 0 :(得分:3)
您可以在下面尝试
val map = List(
Map("a" -> Map(1 -> 1.1)),
Map("a" -> Map(2 -> 2.1)),
Map("b" -> Map(1 -> 1.1)),
Map("c" -> Map(1 -> 1.1)),
Map("c" -> Map(2 -> 2.2))
)
val merged = map.fold(Map.empty[String, List[Map[Int, Double]]]) { (a, b) =>
a ++ b.map { case (k, v) => (k, (v :: a.get(k).toList.flatten).reverse) }
}
merged.foreach(println)
/****** output ******
(a,List(Map(1 -> 1.1), Map(2 -> 2.1)))
(b,List(Map(1 -> 1.1)))
(c,List(Map(1 -> 1.1), Map(2 -> 2.2)))
*********************/
答案 1 :(得分:0)
我将编写自己的函数来执行此操作。首先,类似以下内容的行:
type acc = Map[String, List[Map[Int, Int]]]
@tailrec
def merge(map: Map[String, Map[Int, Int]], acc): acc = map match {
case Nil => acc
case x :: xs =>
val (key, value) = x
if (acc.contains(key)) // append the value to the existing List and then call the merge method again
else // create the new key and call the merge method again
}
确保每次调用merge方法时都使用新的acc(累加器)!