Reputation: 1615
I have two mutable maps in Scala.
val oldMap = Map(10 -> 100, 20 -> 200, 30 -> 300)
val newMap = Map(10 -> 101, 20 -> 200, 30 -> 299, 40 -> 400)
I want to merge newMap
into oldMap
to get outputMap
as below which have all keys from both maps but value is greater of matching key's value.
Map(20 -> 200, 40 -> 400, 10 -> 101, 30 -> 300)
I have tried below and it works but I wanted to know scala way of doing it.
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)
}
Upvotes: 1
Views: 598
Reputation: 143383
You can turn maps into collection of tuples, merge them, group by key and select max value in the group:
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)
Or using groupMapReduce
available since Scala 2.13:
(oldMap.toSeq ++ newMap.toSeq)
.groupMapReduce(_._1)(_._2)(math.max(_,_))
Upvotes: 5
Reputation: 17528
newMap.foldLeft(oldMap){ case (result, (k, newV)) =>
val oldV = result.get(k)
result + (k -> oldV.fold(newV)(newV max _))
}
You start from oldMap
and iterate through newMap
using .foldLeft
. In each iteration you take a key and a value from newMap
, and try to get the value mapped to the same key from the result map (which is the oldMap
at the beginning). You add a new mapping from k
to either the new value, or the max of the new and the old values, in case the old map also contained k
.
It's pretty much the same thing that you have, just in a more functional way.
Upvotes: 3