Scalaz a le concept d'un Semigroup qui capture ce que vous voulez faire ici, et conduit sans doute à la solution la plus courte / la plus propre:
scala> import scalaz._
import scalaz._
scala> import Scalaz._
import Scalaz._
scala> val map1 = Map(1 -> 9 , 2 -> 20)
map1: scala.collection.immutable.Map[Int,Int] = Map(1 -> 9, 2 -> 20)
scala> val map2 = Map(1 -> 100, 3 -> 300)
map2: scala.collection.immutable.Map[Int,Int] = Map(1 -> 100, 3 -> 300)
scala> map1 |+| map2
res2: scala.collection.immutable.Map[Int,Int] = Map(1 -> 109, 3 -> 300, 2 -> 20)
Plus précisément, l 'opérateur binaire pour Map[K, V]
combine les clés des mappes, repliant l V
' opérateur semigroup de sur toutes les valeurs en double. Le semi-groupe standard pour Int
utilise l'opérateur d'addition, vous obtenez donc la somme des valeurs pour chaque clé dupliquée.
Edit : Un peu plus de détails, à la demande de user482745.
Mathématiquement, un semigroupe est juste un ensemble de valeurs, avec un opérateur qui prend deux valeurs de cet ensemble et produit une autre valeur à partir de cet ensemble. Ainsi, les entiers sous addition sont un semi-groupe, par exemple - l' +
opérateur combine deux entiers pour en faire un autre int.
Vous pouvez également définir un semi-groupe sur l'ensemble de "toutes les cartes avec un type de clé et un type de valeur donnés", à condition que vous puissiez proposer une opération qui combine deux cartes pour en produire une nouvelle qui est en quelque sorte la combinaison des deux contributions.
Si aucune clé n'apparaît dans les deux cartes, c'est trivial. Si la même clé existe dans les deux mappages, nous devons combiner les deux valeurs auxquelles la clé mappe. Hmm, n'avons-nous pas juste décrit un opérateur qui combine deux entités du même type? C'est pourquoi dans Scalaz un semigroup pour Map[K, V]
existe si et seulement si un Semigroup pour V
existe - V
le semigroup de est utilisé pour combiner les valeurs de deux mappes affectées à la même clé.
Donc, parce que Int
c'est le type de valeur ici, la "collision" sur la 1
clé est résolue par l'addition entière des deux valeurs mappées (comme c'est ce que fait l'opérateur semigroup d'Int), par conséquent 100 + 9
. Si les valeurs avaient été des chaînes, une collision aurait entraîné une concaténation de chaînes des deux valeurs mappées (encore une fois, parce que c'est ce que fait l'opérateur semigroup pour String).
(Et fait intéressant, parce que la concaténation de chaînes n'est pas commutative - c'est-à-dire que "a" + "b" != "b" + "a"
l'opération de semi-groupe qui en résulte ne l'est pas non plus. Elle map1 |+| map2
est donc différente du map2 |+| map1
cas String, mais pas du cas Int.)
map1 ++ map2