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

How to merge two maps keeping greater of values for matching keys?

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

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

我想将 newMap 合并到 oldMap 中以获得如下所示的 outputMap,它具有来自两个映射的所有键,但值大于匹配键的值。

Map(20 -> 200, 40 -> 400, 10 -> 101, 30 -> 300)

我已经在下面尝试过并且它有效,但我想知道 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)

}
newMap.foldLeft(oldMap){ case (result, (k, newV)) =>
  val oldV = result.get(k)
  result + (k -> oldV.fold(newV)(newV max _))
}

您从 oldMap 开始,然后使用 .foldLeft 遍历 newMap。在每次迭代中,您从 newMap 中获取一个键和一个值,并尝试从结果映射(即开头的 oldMap)中获取映射到相同键的值。您添加一个从 k 到新值或新旧值的最大值的新映射,以防旧映射也包含 k.

它与您拥有的几乎相同,只是功能更强大。

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

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)

或使用自 Scala 2.13 起可用的 groupMapReduce

(oldMap.toSeq ++ newMap.toSeq)
    .groupMapReduce(_._1)(_._2)(math.max(_,_))