xetra11
xetra11

Reputation: 8835

In Kotlin: What is an elegant way to sum two values of a common key from two maps?

I have an existing map that holds simple integer values. I'd like to update that existing map by the value of a given map that holds one of the possible keys.

val originMap = mutableMapOf("Foo" to 10, "Bar" to 5)
val additionalMap = mapOf("Foo" to 4)

// questioned logic

assertThat(originMap).containsEntry("Foo", 14)

Upvotes: 6

Views: 2259

Answers (4)

Yazik
Yazik

Reputation: 81

The above solution has a minor bug that it will add all additional keys in the additionalMap which are not exists in the originalMap to the result. Meaning below will produce output like this:

val originMap = mutableMapOf("Foo" to 10, "Bar" to 5)
val additionalMap = mapOf("Foo" to 4, "Baz" to 3)
additionalMap.forEach { (k, v) -> if (originMap.containsKey(k)) originMap.merge(k, v, Int::plus) }
// Prints {Foo=14, Bar=5, Baz=3}

So same solution without the minor bug would be like below:

additionalMap.forEach { (k, v) -> if (originMap.containsKey(k)) originMap.merge(k, v, Int::plus) }
// Prints {Foo=14, Bar=5}

If worried about JVM specific API: then same would be like

additionalMap.forEach { (k, v) -> if (originMap[k] != null) originMap[k] = (originMap[k] ?: 0) + v }
// Prints {Foo=14, Bar=5}

Upvotes: 0

Similar to previous answer, but without JVM specific API:

additionalMap.forEach { (k, v) -> originMap[k] = (originMap[k] ?: 0) + v }

Upvotes: 1

Willi Mentzel
Willi Mentzel

Reputation: 29844

You could do it like that:

val mergedMap = (originMap.toList() + additionalMap.toList())
        .groupBy({ it.first }, { it.second })
        .map { (key, values) -> key to values.sum() }
        .toMap()

println(mergedMap) // [(Foo, 14), (Bar, 5)]

Try it here!

Upvotes: 7

Todd
Todd

Reputation: 31710

If you want to use originMap in-place rather than declaring a new Map, you can merge addtionalMap into it via a side-effect of forEach:

additionalMap.forEach { (k, v) -> originMap.merge(k, v, Int::plus) }
// Prints {Foo=14, Bar=5}

This will take every key (k) and value (v) from additionalMap and add it to the value in originMap using Int::plus.

Upvotes: 3

Related Questions