mutable.Map 深度合并
mutable.Map deep merge
在 Scala 中有没有一种深度合并两个可变映射的简洁方法?
case class K1(i: Int)
case class K2(i: Int)
def deepMerge(map: mutable.Map[K1, Map[K2, List[Int]]],
mergee: mutable.Map[K1, Map[K2, List[Int]]]
): Unit = ???
示例:
我.
val map = mutable.Map(K1(1) -> Map(K2(1) -> List(1)))
val mergee = mutable.Map(K1(1) -> Map(K2(1) -> List(2)))
deepMerge(map, mergee)
map = mutable.Map(K1(1) -> Map(K2(1) -> List(1, 2)))
II.
val map = mutable.Map(K1(1) -> Map(K2(1) -> List(1)))
val mergee = mutable.Map(K1(1) -> Map(K2(2) -> List(1)))
deepMerge(map, mergee)
map = mutable.Map(K1(1) -> Map(K2(1) -> List(1), K2(2) -> List(1)))
III.
val map = mutable.Map(K1(1) -> Map(K2(1) -> List(1)))
val mergee = mutable.Map(K1(2) -> Map(K2(2) -> List(1)))
deepMerge(map, mergee)
map = mutable.Map(K1(1) -> Map(K2(1) -> List(1)), K1(2) -> Map(K2(2) -> List(1)))
即,如果两个映射中都存在相同的键,则键对应的值 (List[Int]
) 将被合并。
有没有一种方法可以简洁地实现它,避免大量检查特定键是否出现在另一张地图中?使用 scalaz 或 cats 等 FP 库也可以。
也许可以做到。
def deepMerge(mergeA: Map[K1, Map[K2, List[Int]]],
mergeB: Map[K1, Map[K2, List[Int]]]
): Map[K1,Map[K2,List[Int]]] =
(mergeA.toList ++ mergeB.toList).groupMap(_._1)(_._2).map{
case (k1,ms) =>
k1 -> ms.flatMap(_.toList).groupMap(_._1)(_._2).map{
case (k2,ls) => k2 -> ls.flatten
}
}
我还没有用 mutable
地图对其进行测试,但它的工作原理应该大致相同。
我正在使用猫添加另一个答案。
你描述的实际上是 cats.Semigroup 的行为。所以你可以只使用 combine (|+|
) 运算符来深度合并映射:
import cats.implicits._
import cats._
case class K1(i: Int)
case class K2(i: Int)
val map = Map(K1(1) -> Map(K2(1) -> List(1)))
val mergee = Map(K1(1) -> Map(K2(1) -> List(2)))
val deepMerged = map |+| mergee
println(deepMerged) // HashMap(K1(1) -> HashMap(K2(1) -> List(1, 2)))
问题是 cats lib 没有为 mutable.Map
提供 Semigroup 的实例,但您可以从一个不可变的实例中派生它:
import cats.implicits._
import scala.collection.immutable
import scala.collection.mutable
import cats._
//here I derivive Semigroup instance for mutable.Map from instance for immutable.Map
implicit def mutableMapSemigroup[K, V: Semigroup]: Semigroup[mutable.Map[K, V]] = Semigroup[immutable.Map[K, V]].imap(c => mutable.Map.from(c))(c => immutable.Map.from(c))
case class K1(i: Int)
case class K2(i: Int)
val map = mutable.Map(K1(1) -> mutable.Map(K2(1) -> List(1)))
val mergee = mutable.Map(K1(1) -> mutable.Map(K2(1) -> List(2)))
println(map |+| mergee)
但请记住,这实际上是将可变映射转换为不可变映射,然后进行合并,然后再转换回可变映射,因此效率可能不是很高。
在 Scala 中有没有一种深度合并两个可变映射的简洁方法?
case class K1(i: Int)
case class K2(i: Int)
def deepMerge(map: mutable.Map[K1, Map[K2, List[Int]]],
mergee: mutable.Map[K1, Map[K2, List[Int]]]
): Unit = ???
示例:
我.
val map = mutable.Map(K1(1) -> Map(K2(1) -> List(1)))
val mergee = mutable.Map(K1(1) -> Map(K2(1) -> List(2)))
deepMerge(map, mergee)
map = mutable.Map(K1(1) -> Map(K2(1) -> List(1, 2)))
II.
val map = mutable.Map(K1(1) -> Map(K2(1) -> List(1)))
val mergee = mutable.Map(K1(1) -> Map(K2(2) -> List(1)))
deepMerge(map, mergee)
map = mutable.Map(K1(1) -> Map(K2(1) -> List(1), K2(2) -> List(1)))
III.
val map = mutable.Map(K1(1) -> Map(K2(1) -> List(1)))
val mergee = mutable.Map(K1(2) -> Map(K2(2) -> List(1)))
deepMerge(map, mergee)
map = mutable.Map(K1(1) -> Map(K2(1) -> List(1)), K1(2) -> Map(K2(2) -> List(1)))
即,如果两个映射中都存在相同的键,则键对应的值 (List[Int]
) 将被合并。
有没有一种方法可以简洁地实现它,避免大量检查特定键是否出现在另一张地图中?使用 scalaz 或 cats 等 FP 库也可以。
也许可以做到。
def deepMerge(mergeA: Map[K1, Map[K2, List[Int]]],
mergeB: Map[K1, Map[K2, List[Int]]]
): Map[K1,Map[K2,List[Int]]] =
(mergeA.toList ++ mergeB.toList).groupMap(_._1)(_._2).map{
case (k1,ms) =>
k1 -> ms.flatMap(_.toList).groupMap(_._1)(_._2).map{
case (k2,ls) => k2 -> ls.flatten
}
}
我还没有用 mutable
地图对其进行测试,但它的工作原理应该大致相同。
我正在使用猫添加另一个答案。
你描述的实际上是 cats.Semigroup 的行为。所以你可以只使用 combine (|+|
) 运算符来深度合并映射:
import cats.implicits._
import cats._
case class K1(i: Int)
case class K2(i: Int)
val map = Map(K1(1) -> Map(K2(1) -> List(1)))
val mergee = Map(K1(1) -> Map(K2(1) -> List(2)))
val deepMerged = map |+| mergee
println(deepMerged) // HashMap(K1(1) -> HashMap(K2(1) -> List(1, 2)))
问题是 cats lib 没有为 mutable.Map
提供 Semigroup 的实例,但您可以从一个不可变的实例中派生它:
import cats.implicits._
import scala.collection.immutable
import scala.collection.mutable
import cats._
//here I derivive Semigroup instance for mutable.Map from instance for immutable.Map
implicit def mutableMapSemigroup[K, V: Semigroup]: Semigroup[mutable.Map[K, V]] = Semigroup[immutable.Map[K, V]].imap(c => mutable.Map.from(c))(c => immutable.Map.from(c))
case class K1(i: Int)
case class K2(i: Int)
val map = mutable.Map(K1(1) -> mutable.Map(K2(1) -> List(1)))
val mergee = mutable.Map(K1(1) -> mutable.Map(K2(1) -> List(2)))
println(map |+| mergee)
但请记住,这实际上是将可变映射转换为不可变映射,然后进行合并,然后再转换回可变映射,因此效率可能不是很高。