Scala将地图映射数组转换为具有地图列表的地图

时间:2019-09-17 16:29:13

标签: scala

我有一个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个特定映射。正如答案所举例说明的那样,真正的解决方案是通过一种优雅的方式遍历列表,不仅合并列表,而且还需要将地图加载到列表中然后进行合并。

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(累加器)!