如何合并两个地图以保持更大的匹配键值?
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(_,_))
我在 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(_,_))