I need merge maps mapA
andmapB
with pairs of \"name\" - \"phone number\" into the final map, sticking together the values for duplicate keys, separated
While I looked at the other solutions I couldn't believe that there isn't an easier way (or ways as easy as the accepted answer without the need to recreate a Map
, intermediate new lists, etc.). Here are 3 (of many ;-)) solutions I came up with:
Using the keys and mapping the values later:
(mapA.keys.asSequence() + mapB.keys)
.associateWith {
sequenceOf(mapA[it], mapB[it]) // one of the sides may have null values in it (i.e. no entry in the map)...
.filterNotNull()
.distinct()
.toList() // or if you require/prefer, do the following instead: joinToString()
}
Using groupingBy and fold (or have a look at: Group by key and fold each group simultaneously (KEEP)):
(mapA.asSequence() + mapB.asSequence())
.groupingBy { it.key }
.fold(mutableSetOf()) { accumulator, element ->
accumulator.apply {
add(element.value)
}
}
You could also just use an empty String
instead and concatenate in the fold operation the way you need it. My first approach just used a sequenceOf
instead of the MutableSet
. It depends on what you require and what you want to do with the result afterwards.
Using Javas Map.merge, but ignoring duplicates in the value and also just concatenating the values:
val mergedMap: Map = mapA.toMutableMap().apply {
mapB.forEach { key, value ->
merge(key, value) { currentValue, addedValue ->
"$currentValue, $addedValue" // just concatenate... no duplicates-check..
}
}
}
This, of course, can also be written differently, but this way we ensure that mergedMap is still just a Map
when accessed again.