Scalaz có khái niệm về một Semigroup nắm bắt những gì bạn muốn làm ở đây và dẫn đến giải pháp ngắn nhất / sạch nhất:
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)
Cụ thể, toán tử nhị phân để Map[K, V]
kết hợp các khóa của bản đồ, gấp V
toán tử nửa nhóm trên bất kỳ giá trị trùng lặp nào. Nhóm bán kết chuẩn để Int
sử dụng toán tử bổ sung, do đó bạn có được tổng giá trị cho mỗi khóa trùng lặp.
Chỉnh sửa : Chi tiết hơn một chút, theo yêu cầu của người dùng482745.
Về mặt toán học, một nửa nhóm chỉ là một tập hợp các giá trị, cùng với một toán tử lấy hai giá trị từ tập đó và tạo ra một giá trị khác từ tập đó. Vì vậy, các số nguyên dưới đây là một nửa nhóm, ví dụ - +
toán tử kết hợp hai số nguyên để tạo một số nguyên khác.
Bạn cũng có thể xác định một nửa nhóm trên tập hợp "tất cả các bản đồ với loại khóa và loại giá trị nhất định", miễn là bạn có thể đưa ra một số thao tác kết hợp hai bản đồ để tạo ra một bản đồ mới bằng cách nào đó kết hợp cả hai bản đồ đầu vào.
Nếu không có phím nào xuất hiện trong cả hai bản đồ thì đây là chuyện nhỏ. Nếu cùng một khóa tồn tại trong cả hai bản đồ, thì chúng ta cần kết hợp hai giá trị mà khóa ánh xạ tới. Hmm, chúng ta vừa mô tả một toán tử kết hợp hai thực thể cùng loại phải không? Đây là lý do tại sao trong Scalaz một nhóm bán kết Map[K, V]
tồn tại khi và chỉ khi một nhóm bán kết V
tồn tại - V
nhóm bán kết được sử dụng để kết hợp các giá trị từ hai bản đồ được gán cho cùng một khóa.
Vì vậy, vì Int
là loại giá trị ở đây, "xung đột" trên 1
khóa được giải quyết bằng phép cộng số nguyên của hai giá trị được ánh xạ (như đó là điều mà toán tử semigroup thực hiện), do đó 100 + 9
. Nếu các giá trị là Chuỗi, một xung đột sẽ dẫn đến kết hợp chuỗi của hai giá trị được ánh xạ (một lần nữa, vì đó là điều mà toán tử semigroup cho Chuỗi thực hiện).
(Và thật thú vị, vì nối chuỗi không phải là giao hoán - nghĩa là "a" + "b" != "b" + "a"
- hoạt động semigroup kết quả cũng không. Vì vậy, map1 |+| map2
khác với map2 |+| map1
trong trường hợp Chuỗi, nhưng không phải trong trường hợp Int.)
map1 ++ map2