Scalaz a le concept d'un Semigroupe qui capture ce que vous voulez faire ici, et mène à la solution la plus courte et 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 cartes, le pliage V
L'opérateur de semigroupe de l'auteur sur toutes les valeurs en double. Le semigroupe standard pour Int
utilise l'opérateur d'addition, de sorte que vous obtenez la somme des valeurs pour chaque clé dupliquée.
Editar : Un peu plus de détails, à la demande de l'utilisateur 482745.
Mathématiquement, un semigroupe est juste un ensemble de valeurs, ainsi qu'un opérateur qui prend deux valeurs de cet ensemble, et produit une autre valeur de cet ensemble. Ainsi, les entiers sous addition sont un semigroupe, par exemple - le +
L'opérateur combine deux entiers pour en faire un autre entier.
Vous pouvez également définir un semigroupe sur l'ensemble de "toutes les cartes avec un type de clé et un type de valeur donnés", tant que vous pouvez trouver une opération qui combine deux cartes pour en produire une nouvelle qui est en quelque sorte la combinaison des deux entrées.
S'il n'y a pas de clés qui apparaissent dans les deux cartes, c'est trivial. Si la même clé existe dans les deux cartes, nous devons combiner les deux valeurs auxquelles la clé correspond. Hmm, ne venons-nous pas de décrire un opérateur qui combine deux entités du même type ? C'est pourquoi, dans Scalaz, un semigroupe de Map[K, V]
existe si et seulement si un Semigroup pour V
existe - V
Le semigroupe de l'auteur est utilisé pour combiner les valeurs de deux cartes qui sont affectées à la même clé.
Donc, parce que Int
est le type de valeur ici, la "collision" sur le 1
est résolu par l'addition entière des deux valeurs mappées (car c'est ce que fait l'opérateur semigroupe de Int), d'où 100 + 9
. Si les valeurs avaient été des chaînes de caractères, une collision aurait entraîné la concaténation des deux valeurs mappées (encore une fois, parce que c'est ce que fait l'opérateur de semigroupe pour les chaînes de caractères).
(Et de façon intéressante, parce que la concaténation des chaînes de caractères n'est pas commutative - c'est-à-dire, "a" + "b" != "b" + "a"
- l'opération de semigroupe qui en résulte ne l'est pas non plus. Donc map1 |+| map2
est différent de map2 |+| map1
dans le cas de String, mais pas dans le cas de Int).
0 votes
Le plus facile est
map1 ++ map2
4 votes
@Seraf En fait, cela ne fait que "fusionner" les cartes, en ignorant les doublons au lieu d'additionner leurs valeurs.
1 votes
@ZeynepAkkalyoncuYilmaz Exact, j'aurais dû mieux lire la question, part dans la honte