Is there an easy way to merge two maps of Map<S...
# announcements
d
Is there an easy way to merge two maps of Map<String, Foo> into one map? I know the keys of the two maps are distinct from each other. I.e. I don't want to have Map<String,List<Foo>> as a resulting map.
r
map1 + map2
d
Okay.. sometimes it's not a good idea to oversimplify the question. Let's say I have n maps instead of just two 🙂
List<Map<String, Foo>>
r
maps.reduce { accumulator, next -> accumulator + next }
d
oh
that is so much better than what I had, thank you.
r
Won’t work for an empty list though… you’d need to use fold for that
d
that's fine, the code guarantees the list won't be empty
r
Actually
maps.reduceOrNull { accumulator, next -> accumulator + next } ?: emptyMap()
would work
d
Using something like
buildMap { maps
.forEach { putAll(it) }
}
would avoid creating a new map for each iteration though...
Or fold with a mutablemap
n
Yeah, you really don't ever want to use a container + in a loop
Makes a linear operation quadratic
d
My brain still has a hard time to work with reduce and fold. Merging data with a few loops and a "container" is very natural, translating it to fold just melts my neurons.
had the next one where I tried to merge
List<Map<String, List<String>>
into
Map<String, List<String>>
. This time the values for the same keys should be combined. Came up with this
Copy code
val familyToCodes = mutableMapOf<String, MutableList<String>>()

allAssets.forEach { assets ->
    assets.forEach { (attributeFamily, assetCodes) ->
        familyToCodes.getOrPut(attributeFamily) { mutableListOf() }
            .addAll(assetCodes)
    }
}
failed to convert it to fold or buildMaps 😉
d
Copy code
val immutableFamilyToCodesMap = buildMap {
allAssets.forEach { assets ->
    assets.forEach { (attributeFamily, assetCodes) ->
        getOrPut(attributeFamily) { mutableListOf() }
            .addAll(assetCodes)
    }
}
}
Same thing really, just leaves you with a
Map
that's not mutable at the end...
d
Okay. I think in this case it makes the code less readable (not the biggest fan of assuming getOrPut belongs to the builder)
n
I think @dave08’s buildMap solution is probably best, especially if you have trouble with reduce/fold
his first one I mean
oops wrong dave
The real way you want to do this one is actually
groupBy
Or rather,
groupingBy
with some aggregate etc follow up
but if you are already struggling with fold/reduce you may not like it. I think the buildMap solutions are a very nice compromise; buildMap has a receiver with the MutableMap API, that's not really an assumption per se