如何合并两个地图以保留更大的匹配键值?

con*_*fun 1 merge dictionary scala scala-collections

我在 Scala 中有两个可变映射。

val oldMap = Map(10 -> 100, 20 -> 200, 30 -> 300)
val newMap = Map(10 -> 101, 20 -> 200, 30 -> 299, 40 -> 400)
Run Code Online (Sandbox Code Playgroud)

我想合并newMapoldMap得到outputMap如下具有从两个地图的所有键,但其值越大匹配键的值。

Map(20 -> 200, 40 -> 400, 10 -> 101, 30 -> 300)
Run Code Online (Sandbox Code Playgroud)

我在下面尝试过并且它有效,但我想知道 Scala 的做法。

import scala.collection.mutable.Map

object Test extends App {

  val oldMap = Map(10 -> 100, 20 -> 200, 30 -> 300)
  val newMap = Map(10 -> 101, 20 -> 200, 30 -> 299, 40 -> 400)
  val outputMap = mergeMap(oldMap, newMap)

  println(outputMap)

  def mergeMap(map1: Map[Int, Int], map2: Map[Int, Int]): Map[Int, Int] = {
    val map1Keys = map2.keys
    val itr = map1Keys.iterator
    while (itr.hasNext)
    {
      val id = itr.next
      if (! map1.contains(id)){ // key not present in map1, INSERT
        map1(id) = map2(id)
      }
      else { // key present in map1, UPDATE
        if (map2(id) > map1(id)){
          map1(id) = map2(id)
        }
      }

    }
    map1
  }

  def commonMapKeys[A, B](a: Map[A, B], b: Map[A, B]): scala.collection.Set[A] = a.keySet.intersect(b.keySet)

}
Run Code Online (Sandbox Code Playgroud)

Gur*_*ron 5

您可以将映射转换为元组集合,合并它们,按键分组并选择组中的最大值:

val oldMap = Map(10 -> 100, 20 -> 200, 30 -> 300)
val newMap = Map(10 -> 101, 20 -> 200, 30 -> 299, 40 -> 400)
(oldMap.toSeq ++ newMap.toSeq)
  .groupBy(_._1)
  .mapValues(_.map(_._2).max)
Run Code Online (Sandbox Code Playgroud)

或者使用groupMapReduce自 Scala 2.13 起可用:

(oldMap.toSeq ++ newMap.toSeq)
    .groupMapReduce(_._1)(_._2)(math.max(_,_))
Run Code Online (Sandbox Code Playgroud)