我想合并嵌套的地图,但我无法弄清楚如何合并内部地图。
var a = Map[String,Map[String,String]]()
a = a + ("key1" -> Map("subkey1" -> "a"))
a = a + ("key1" -> Map("subkey2" -> "b"))
a = a + ("key2" -> Map("subkey1" -> "c"))
我想合并所有这些,以便得到以下结果:
Map("key1" -> Map("subkey1" -> "a", "subkey2" -> "b"), "key2" -> Map("subkey1" -> "c"))
这有什么标准方法吗?
答案 0 :(得分:1)
如果可以使用Scalaz - semigroups可能会有所帮助:
import scalaz._, Scalaz._
val map1 = Map("key1" -> Map("subkey1" -> "a"))
val map2 = Map("key1" -> Map("subkey2" -> "b"))
val map3 = Map("key2" -> Map("subkey1" -> "c"))
scala> map1 |+| map2 |+| map3
res0: scala.collection.immutable.Map[String,scala.collection.immutable.Map[String,String]] =
Map(key2 -> Map(subkey1 -> c), key1 -> Map(subkey2 -> b, subkey1 -> a))
唯一限制 - 您的值应定义Semigroup以便处理冲突:
trait A
object A1 extends A
object A2 extends A
implicit val ASemigroup = new Semigroup[A] {
def append(a: A, b: => A) : A = a //"choose first" strategy
}
val map1 = Map("key1" -> Map("subkey1" -> (A1: A)))
val map2 = Map("key1" -> Map("subkey1" -> (A2: A)))
scala> map1 |+| map2
res8: scala.collection.immutable.Map[String,scala.collection.immutable.Map[String,A]] =
Map(key1 -> Map(subkey1 -> A1$@2cb79bd1))
顺便说一下,字符串已经在它们上定义了Semigroup,因此碰撞会导致字符串在那里连接。
答案 1 :(得分:0)
内置的内容并不适用于此,但getOrElse
是您的朋友。如果您确定没有子图集合,则逻辑的核心看起来像
val x = a.getOrElse(key, mutable.Map.empty[String,String])
a = a + (key -> (x ++ subMap))
如果您可能发生冲突,则需要执行++
以外的操作 - 可能再次使用相同的技巧获取子密钥并更新值(如果存在)。
答案 2 :(得分:0)
似乎没有为此提供直接方法。您可以提供辅助方法。
def mergeUpdate[K1, K2, V](base: Map[K1, Map[K2, V]], tuple: (K1, Map[K2, V])) = {
base + (tuple._1 -> (base.getOrElse(tuple._1, Map.empty) ++ tuple._2))
}
然后重写你的代码:
var a = Map[String,Map[String,String]]()
a = mergeUpdate(a, ("key1" -> Map("subkey1" -> "a")))
a = mergeUpdate(a, ("key1" -> Map("subkey2" -> "b")))
a = mergeUpdate(a, ("key2" -> Map("subkey1" -> "c")))
// =>
a: scala.collection.immutable.Map[String,Map[String,String]] = Map(key1 -> Map(subkey1 -> a, subkey2 -> b), key2 -> Map(subkey1 -> c))
答案 3 :(得分:0)
如果您可以提取其他依赖项,可以试试这个
scala> import com.daodecode.scalax.collection.extensions._
import com.daodecode.scalax.collection.extensions._
scala> val m1 = "key1" -> Map("subkey1" -> "a")
m1: (String, scala.collection.immutable.Map[String,String]) = (key1,Map(subkey1 -> a))
scala> val m2 = "key1" -> Map("subkey2" -> "b")
m2: (String, scala.collection.immutable.Map[String,String]) = (key1,Map(subkey2 -> b))
scala> val m3 = "key2" -> Map("subkey1" -> "c")
m3: (String, scala.collection.immutable.Map[String,String]) = (key2,Map(subkey1 -> c))
scala> Seq(m1, m2, m3).toCompleteMap.
mapValues(_.foldLeft(Map.empty[String,String]){
case (acc, m) => acc.mergedWith(m)(_ + _)})
res0: scala.collection.immutable.Map[String,scala.collection.immutable.Map[String,String]] = Map(key2 -> Map(subkey1 -> c), key1 -> Map(subkey1 -> a, subkey2 -> b))
toCompleteMap和mergedWith是来自https://github.com/jozic/scalax-collection的扩展方法。它已发布到maven central
(_ + _)
这是您自己的碰撞解决功能