В Scalaz есть концепция полугруппы, которая фиксирует то, что вы хотите здесь сделать, и приводит, возможно, к кратчайшему / наиболее чистому решению:
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)
В частности, бинарный оператор для Map[K, V]
комбинирует ключи карт, складывая V
оператор полугруппы по любым дублирующимся значениям. Стандартная полугруппа для Int
использует оператор сложения, поэтому вы получаете сумму значений для каждого дублирующего ключа.
Изменить : немного больше деталей, согласно запросу пользователя 482745.
Математически полугруппа - это просто набор значений вместе с оператором, который принимает два значения из этого набора и производит другое значение из этого набора. Таким образом, +
добавляемые целые числа - это, например, полугруппа - оператор объединяет два целых числа для создания другого целого.
Вы также можете определить полугруппу по набору «всех карт с заданным типом ключа и типом значения», при условии, что вы можете придумать какую-то операцию, которая объединяет две карты, чтобы создать новую, которая каким-то образом является комбинацией двух. входы.
Если на обеих картах нет ключей, это тривиально. Если один и тот же ключ существует на обеих картах, то нам нужно объединить два значения, на которые отображается ключ. Хм, разве мы не описали оператор, который объединяет два объекта одного типа? Вот почему в Scalaz полугруппа для Map[K, V]
существует тогда и только тогда, когда полугруппа для V
существует - V
используется полугруппа для объединения значений из двух карт, которые назначены одному и тому же ключу.
Так как Int
здесь тип значения, «коллизия» на 1
ключе разрешается путем целочисленного сложения двух отображенных значений (как это делает оператор полугруппы Int), следовательно 100 + 9
. Если бы значения были Strings, коллизия привела бы к объединению строк двух сопоставленных значений (опять же, потому что это то, что делает оператор полугруппы для String).
(И что интересно, поскольку конкатенация строк не является коммутативной, то есть "a" + "b" != "b" + "a"
результирующая операция полугруппы также не является. Таким образом, map1 |+| map2
она отличается от map2 |+| map1
случая String, но не от случая Int.)
map1 ++ map2