在Scala中递归合并嵌套的Map

时间:2014-04-29 09:15:55

标签: scala map

我有一些嵌套的地图,如:

val map1 = Map("key1"->1, "key2"->Map("x"->List(1,2)))
val map2 = Map("key3"->3, "key2"->Map("y"->List(3,4)))

我想合并它们以获得结果图,如;

val res = Map("key1"->1, "key2"->Map("x"->List(1,2), "y"->List(3,4)), "key3"->3)

因此嵌套地图也应该合并。 地图和嵌套地图的类型可以假设为Map [String,Any]。如果两个映射具有冲突键(例如,相同键的值不同,除了该值是嵌套映射),则认为是异常。

这有一些优雅的解决方案吗? 谢谢!

2 个答案:

答案 0 :(得分:2)

以下内容如何:

  type MapType = Map[String, Any]

  def merge(map1 : MapType, map2 : MapType) = (map1.keySet ++ map2.keySet)
    .map(key => key -> mergeValues(map1.get(key), map2.get(key)))
    .toMap

  private def mergeValues(o1 : Option[Any], o2 : Option[Any]) = (o1, o2) match {
    case (Some(v1 : MapType), Some(v2 : MapType)) => v1 ++ v2
    case _ => (o1 orElse o2).get
  }

您可以修改mergeValues函数以支持其他情况(即当相同的键指向2个非映射值的情况时 - 此时将返回第一个值)。

答案 1 :(得分:2)

type MapType = Map[String, Any]

def merge(map1 : MapType, map2 : MapType) = (map1.keySet ++ map2.keySet)
  .map(key => key -> mergeValues(map1.get(key), map2.get(key)))
  .toMap

private def mergeValues(o1 : Option[Any], o2 : Option[Any]) = (o1, o2) match {
  case (Some(v1), Some(v2)) => merge(v1.asInstanceOf[MapType], v2.asInstanceOf[MapType])
  case _ => (o1 orElse o2).get
}

norbert-radyk的改进版本:

  • darkjh
  • 建议的多个嵌套级别支持
  • Scala 2.11兼容性以避免此错误:non-variable type argument String in type pattern scala.collection.immutable.Map[String,Any] (the underlying of MapType) is unchecked since it is eliminated by erasure case (Some(v1 : MapType), Some(v2 : MapType)) => v1 ++ v2