Scalaz ma koncepcję półgrupy, która przechwytuje to, co chcesz tutaj zrobić, i prowadzi do prawdopodobnie najkrótszego / najczystszego rozwiązania:
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)
W szczególności, operator binarny for Map[K, V]
łączy klucze map, V
zawijając operator półgrupy nad zduplikowanymi wartościami. Standardowa półgrupa dla Int
używa operatora dodawania, więc otrzymujesz sumę wartości dla każdego zduplikowanego klucza.
Edycja : trochę więcej szczegółów, zgodnie z prośbą użytkownika482745.
Matematycznie półgrupa to po prostu zbiór wartości wraz z operatorem, który pobiera dwie wartości z tego zbioru i tworzy inną wartość z tego zbioru. Na przykład liczby całkowite są półgrupą - +
operator łączy dwie liczby całkowite, aby utworzyć kolejną liczbę int.
Możesz także zdefiniowaćpółgrupę na zbiorze "wszystkich map z podanym typem klucza i typem wartości", o ile możesz wymyślić jakąś operację, która łączy dwie mapy w celu utworzenia nowej, która jest w jakiś sposób połączeniem tych dwóch wejścia.
Jeśli nie ma kluczy, które pojawiają się na obu mapach, jest to trywialne. Jeśli ten sam klucz istnieje w obu mapach, musimy połączyć dwie wartości, na które mapuje klucz. Hmm, czy nie opisaliśmy właśnie operatora, który łączy dwie jednostki tego samego typu? Dlatego w Scalaz półgrupa for Map[K, V]
istnieje wtedy i tylko wtedy, gdy półgrupa dla V
istnieje - V
jest używana do łączenia wartości z dwóch map, które są przypisane do tego samego klucza.
Tak więc, ponieważ Int
jest to typ wartości, "kolizja" 1
klucza jest rozwiązywana przez dodanie liczb całkowitych dwóch odwzorowanych wartości (tak jak robi to operator półgrupy Int) 100 + 9
. Gdyby wartości były ciągami, kolizja spowodowałaby konkatenację ciągów dwóch odwzorowanych wartości (ponownie, ponieważ tak robi operator półgrupy dla ciągu).
(Co ciekawe, ponieważ konkatenacja ciągów nie jest przemienna - to znaczy "a" + "b" != "b" + "a"
- wynikowa operacja półgrupowa też nie jest. Więc map1 |+| map2
różni się od map2 |+| map1
przypadku String, ale nie w przypadku Int).
map1 ++ map2