veränderlich.Map Deep Merge
Gibt es eine präzise Möglichkeit, zwei veränderbare Karten in Scala tief zusammenzuführen?
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 = ???
Beispiele:
ICH.
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)))
Das heißt, wenn in beiden Karten derselbe Schlüssel dargestellt ist, werden die Werte, denen die Schlüssel entsprechen ( List[Int]
), zusammengeführt.
Gibt es eine Möglichkeit, es präzise zu implementieren, ohne zu prüfen, ob der jeweilige Schlüssel in einer anderen Karte angezeigt wird oder nicht? Die Verwendung von FP-Bibliotheken wie Scalaz oder Katzen ist ebenfalls in Ordnung.
Antworten
Ich füge eine weitere Antwort mit Katzen hinzu.
Was Sie beschreiben, ist eigentlich das Verhalten von Katzen . Sie können also einfach den |+|
Operator comb ( ) verwenden, um Karten tief zusammenzuführen:
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)))
Das Problem ist, dass cat lib keine Instanz von Semigroup für bereitstellt mutable.Map
, aber Sie könnten sie von einer für unveränderlich ableiten:
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)
Beachten Sie jedoch, dass dies tatsächlich eine veränderbare Karte in eine unveränderliche konvertiert, dann zusammengeführt und dann wieder in die veränderliche Karte konvertiert, sodass es wahrscheinlich nicht sehr effizient ist.
Das könnte es tun.
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
}
}
Ich habe es nicht mit mutable
Maps getestet, aber es sollte mehr oder weniger gleich funktionieren.