I've got a list maps, and I'd like to merge them i...
# functional
r
I've got a list maps, and I'd like to merge them into a single map, with a value merge function. Is there one such a collection operation?
sticking to pure Kotlin I don't think there's anything simple built-in, but you could
Copy code
buildMap {
    for (map in listOfMaps) {
        map.mapValuesTo(this) { (key, value) ->
            if (contains(key)) mergeValues(getValue(key), value) else value
        }
    }
}
r
This is what I came up with:
Copy code
CardMessageLinksDto(it.fold(mapOf<Uuid, CardMessageLinkDto>()) { acc, links ->
                    links.cardMessageLinks.fold(acc) { newLinks, link ->
                        val current = newLinks[link.uuid]
                        if (current != null) {
                            if (current.updated != null
                                && link.updated != null
                                && <http://current.updated.at|current.updated.at> < <http://link.updated.at|link.updated.at>) {
                                newLinks + (link.uuid to link)
                            } else
                            newLinks
                        } else {
                            newLinks + (link.uuid to link)
                        }
                    }
                }.values.toList())
e
I suppose
Copy code
listOfMaps.asSequence()
    .flatMap { it.entries }
    .groupingBy { it.key }
    .aggregate { _, acc, (_, value), first -> if (first) value else mergeValues(acc, value) }
could look a bit more functional
s
funny enough, I think the Java stream API is much more ergonomic (and efficient) here than anything included in the Kotlin stdlib
Copy code
mapList.stream()
        .flatMap(it -> it.entrySet().stream())
        .collect(toMap(
                Map.Entry::getKey,
                Map.Entry::getValue,
                Foo::mergingFunction));
e
I suppose that if you didn't mind some extra intermediates
Copy code
listOfMaps
    .flatMap { it.entries }
    .groupBy { it.key }
    .mapValues { entries ->
        val values = entries.map { it.value }
        values.reduce { value1, value2 -> mergeValues(value1, value2) }
    }
is pretty readable. and still O(N) in total entries as opposed to reactormonk's
map + pair
solution turning an O(N) problem into an O(N^2) solution