scala:合并两个可变集的可变映射的最佳方法

时间:2016-05-04 14:44:31

标签: scala scala-collections

scala合并两个可变集的可变映射的最佳方法是什么?该操作必须是可交换的。我尝试过的东西看起来很难看......

import scala.collection.mutable
var d1 = mutable.Map[String, mutable.SortedSet[String]]()
var d2 = mutable.Map[String, mutable.SortedSet[String]]()

// adding some elements.  Accumulating nimals with the set of sounds they make.
d1.getOrElseUpdate("dog", mutable.SortedSet[String]("woof"))
d2.getOrElseUpdate("cow", mutable.SortedSet[String]("moo"))
d2.getOrElseUpdate("dog", mutable.SortedSet[String]("woof", "bark"))

魔法(这是可交换的!)

scala.collection.mutable.Map[String,scala.collection.mutable.SortedSet[String]] =
Map(dog -> TreeSet(bark, woof), cow -> TreeSet(moo))

基本上,我想覆盖++的定义来合并匹配地图键的集合。请注意     d1 ++ d2给出了正确的答案,而d2 ++ d1则没有(因此++在这里不可交换)。

1 个答案:

答案 0 :(得分:2)

对于结果Map中的每个键,您必须合并(++)来自Setd1的值d2那把钥匙。

对于mutable.Mapmutable.Set,当您更新其中一个Map时,实施非常简单:

for ((key, values) <- d2) 
  d1.getOrElseUpdate(key, mutable.SortedSet.empty) ++= values

您实际上可以创建一个空的mutable.Map,并使用该代码以任意顺序使用d1d2(以及其他Map s)进行更新。

您可以将此操作包装在以下函数中:

val d1 = mutable.Map[String, mutable.SortedSet[String]](
  "dog" -> mutable.SortedSet("woof"), 
  "cow" -> mutable.SortedSet("moo"))
val d2 = mutable.Map[String, mutable.SortedSet[String]](
  "dog" -> mutable.SortedSet("woof", "bark"))

def updateMap[A, B : Ordering]( // `Ordering` is a requirement for `SortedSet`
  d1: mutable.Map[A, mutable.SortedSet[B]])(
  // `Iterable`s are enough here, but allow to pass a `Map[A, Set[B]]`
  d2: Iterable[(A, Iterable[B])] 
): Unit =
  for ((key, values) <- d2)
    d1.getOrElseUpdate(key, mutable.SortedSet.empty) ++= values

// You can call 
// `updateMap(d1)(d2)` or 
// `updateMap(d2)(d1)` to achieve the same result (but in different variables)

对于不可变的Map,一种可能的实现是:

(
  for (key <- d1.keySet ++ d2.keySet)
  yield key -> (d1.getOrElse(key, Set.empty) ++ d2.getOrElse(key, Set.empty))
).toMap

其他可能更有效但可能稍微复杂的实现也是可能的。