首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >mutable.Map深度合并

mutable.Map深度合并
EN

Stack Overflow用户
提问于 2020-12-01 06:05:27
回答 2查看 114关注 0票数 1

有没有一种简洁的方法可以深入合并Scala中的两个可变映射?

代码语言:javascript
复制
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 = ???

示例:

I.

代码语言:javascript
复制
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.

代码语言:javascript
复制
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.

代码语言:javascript
复制
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])被合并。

是否有一种方法可以简洁地实现它,避免大量检查是否在另一张地图中显示了特定的密钥?使用FP库,如金刚石或猫也是可以的。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-12-01 08:40:43

我要用猫来补充另一个答案。

您所描述的实际上是cats.Semigroup的行为。因此,您只需使用组合(|+|)运算符进行深度合并映射:

代码语言:javascript
复制
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没有为mutable.Map提供半群的实例,但您可以从一个不可变的实例中派生它:

代码语言:javascript
复制
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)

但是请记住,这实际上是将可变的映射转换为不可变的,然后进行合并,然后再转换回可变的映射,所以它可能不是很有效。

票数 3
EN

Stack Overflow用户

发布于 2020-12-01 07:29:01

这样就行了。

代码语言:javascript
复制
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地图对它进行测试,但它的工作原理大致相同。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65085487

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档