Scalaz tiene el concepto de un Semigrupo que captura lo que quiere hacer aquí y conduce a la solución más corta / más limpia:
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)
Específicamente, el operador binario para Map[K, V]
combina las claves de los mapas, doblando V
el operador del semigrupo sobre cualquier valor duplicado. El semigrupo estándar para Int
utiliza el operador de suma, por lo que obtiene la suma de valores para cada clave duplicada.
Editar : Un poco más de detalle, según la solicitud del usuario 482745.
Matemáticamente, un semigrupo es solo un conjunto de valores, junto con un operador que toma dos valores de ese conjunto y produce otro valor a partir de ese conjunto. Entonces, los enteros bajo suma son un semigrupo, por ejemplo: el +
operador combina dos entradas para hacer otro int.
También puede definir un semigrupo sobre el conjunto de "todos los mapas con un tipo de clave y un tipo de valor dados", siempre que pueda encontrar alguna operación que combine dos mapas para producir uno nuevo que de alguna manera sea la combinación de los dos entradas
Si no hay claves que aparecen en ambos mapas, esto es trivial. Si existe la misma clave en ambos mapas, entonces necesitamos combinar los dos valores a los que se asigna la clave. Hmm, ¿no acabamos de describir un operador que combina dos entidades del mismo tipo? Es por eso que en Scalaz Map[K, V]
existe un semigrupo para si y solo si V
existe un semigrupo para - V
el semigrupo se usa para combinar los valores de dos mapas que se asignan a la misma clave.
Entonces, como Int
es el tipo de valor aquí, la "colisión" en la 1
clave se resuelve mediante la suma entera de los dos valores mapeados (ya que eso es lo que hace el operador de semigrupo de Int), por lo tanto 100 + 9
. Si los valores hubieran sido Strings, una colisión hubiera resultado en la concatenación de los dos valores mapeados (de nuevo, porque eso es lo que hace el operador de semigrupo para String).
(Y curiosamente, debido a que la concatenación de cadenas no es conmutativa, es decir, "a" + "b" != "b" + "a"
la operación de semigrupo resultante tampoco lo map1 |+| map2
es . Por lo tanto, es diferente de map2 |+| map1
en el caso de la cadena, pero no en el caso de Int.)
map1 ++ map2