天天看點

scala 兩個map合并,key相同時value相加

版權聲明:本文由董可倫首發于https://dongkelun.com,非商業轉載請注明作者及原創出處。商業轉載請聯系作者本人。 https://blog.csdn.net/dkl12/article/details/80246048

我的原創位址:

https://dongkelun.com/2018/04/01/scalaMapAdd/

1、先看一下map自帶的合并操作的效果

val map1 = Map("key1" -> 1, "key2" -> 3, "key3" -> 5)
val map2 = Map("key2" -> 4, "key3" -> 6, "key5" -> 10)
println(map1 + ("key1" -> 3))
println(map1 ++ map2)           

結果:

Map(key1 -> 3, key2 -> 3, key3 -> 5)
Map(key1 -> 1, key2 -> 4, key3 -> 6, key5 -> 10)           

可以看到現有的方法在key相同時,沒有将value相加,而是操作符右邊的值把左邊的值覆寫掉了。

2、利用map函數

2.1 為了便于了解先看如下代碼

代碼:

val map1 = Map("key1" -> 1, "key2" -> 3, "key3" -> 5)
map1.map { t => println(t._1, t._2) }           
(key1,1)
(key2,3)
(key3,5)           

可以看出map函數會周遊集合中的每個元素

可以為其指定傳回結果:

println(map1.map { t => 2 })
println(map1.map { t => t._1 -> t._2 })           
List(2, 2, 2)
Map(key1 -> 1, key2 -> 3, key3 -> 5)           

可以看出,該函數傳回結果類型可以不同,并且會将我們指定的值,組成一個集合,并自動判斷傳回類型。

2.2 合并兩個map

val map1 = Map("key1" -> 1, "key2" -> 3, "key3" -> 5)
val map2 = Map("key2" -> 4, "key3" -> 6, "key5" -> 10)
val mapAdd1 = map1 ++ map2.map(t => t._1 -> (t._2 + map1.getOrElse(t._1, 0)))
println(mapAdd1)           

其中map.getOrElse(key,default):如果map中有這個key,則傳回對應的value,否在傳回default

Map(key1 -> 1, key2 -> 7, key3 -> 11, key5 -> 10)           

3、用foldLeft

3.1 文法

以下三種寫法是相等的:

List(1, 2, 3, 4).foldLeft(0)((sum, i) => sum + i)
(List(1, 2, 3, 4) foldLeft 0)((sum, i) => sum + i)
(0 /: List(1, 2, 3, 4))(_ + _)             

為了便于了解,先看下面代碼:

(0 /: List(1, 2, 3, 4))((sum, i) => {
  println(s"sum=${sum} i=${i}")
  sum
})           
sum=0 i=1
sum=0 i=2
sum=0 i=3
sum=0 i=4           

該函數的功能是從左往右周遊右邊操作類型List,而sum對應的是對應的左邊的0,該函數要求傳回值類型和左邊類型一緻,上面的例子中傳回值是Int。

同理,兩個Map的代碼如下:

val map1 = Map("key1" -> 1, "key2" -> 3, "key3" -> 5)
val map2 = Map("key2" -> 4, "key3" -> 6, "key5" -> 10)
(map1 /: map2)((map, kv) => {
  println(s"map=${map} kv=${kv}")
  map
})           
map=Map(key1 -> 1, key2 -> 3, key3 -> 5) kv=(key2,4)
map=Map(key1 -> 1, key2 -> 3, key3 -> 5) kv=(key3,6)
map=Map(key1 -> 1, key2 -> 3, key3 -> 5) kv=(key5,10)           

從結果中可以看出左邊map對應的是map1整體,而不是周遊map1

3.2 合并兩個map:

val map1 = Map("key1" -> 1, "key2" -> 3, "key3" -> 5)
val map2 = Map("key2" -> 4, "key3" -> 6, "key5" -> 10)
val mapAdd2 = (map1 /: map2)((map, kv) => {
  map + (kv._1 -> (kv._2 + map.getOrElse(kv._1, 0)))
})
println(mapAdd2)           
Map(key1 -> 1, key2 -> 7, key3 -> 11, key5 -> 10)           

4、用模式比對

在網上查的有的用的模式比對,我感覺在這裡這樣用就是多餘~

附上代碼:

val mapAdd2 = map1 ++ map2.map { case (key, value) => key -> (value + map1.getOrElse(key, 0)) }
println(mapAdd2)
val mapAdd3 = (map1 /: map2) {
  case (map, kv) => {
    map + (kv._1 -> (kv._2 + map.getOrElse(kv._1, 0)))
  }
}
println(mapAdd3)
val mapAdd4 = (map1 /: map2) {
  case (map, (k, v)) => {
    map + (k -> (v + map.getOrElse(k, 0)))
  }
}
println(mapAdd4)           

結果是一樣的:

Map(key1 -> 1, key2 -> 7, key3 -> 11, key5 -> 10)
Map(key1 -> 1, key2 -> 7, key3 -> 11, key5 -> 10)
Map(key1 -> 1, key2 -> 7, key3 -> 11, key5 -> 10)           

參考

https://www.cnblogs.com/tugeler/p/5134862.html