简体   繁体   English

在 Kotlin 中:从两个映射中对一个公共键的两个值求和的优雅方法是什么?

[英]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)

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!在这里试试吧!

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 :如果你想使用originMap就地而不是宣布一个新的Map ,你可以合并addtionalMap通过的副作用为它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 .这将从additionalMap获取每个键 ( k ) 和值 ( v ),并使用Int::plus将其添加到originMap的值。

与之前的答案类似,但没有 JVM 特定的 API:

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

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.上述方案有一个小错误,这将增加所有附加键在additionalMap其中不存在于originalMap的结果。 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如果担心 JVM 特定的 API:那么就像

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM