用 Kotlin:从两个映射中以优雅的方式求取共同键的两个值的和是什么?

huangapple go评论65阅读模式
英文:

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

问题

我有一个现有的地图,保存着简单的整数值。我想通过一个给定的地图的值来更新这个现有的地图,该地图保存着可能的键之一。

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

// 有疑问的逻辑

assertThat(originMap).containsEntry("Foo", 14)
英文:

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)

答案1

得分: 5

你可以像这样做:

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

在这里尝试!

英文:

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!

答案2

得分: 3

如果您想要原地使用originMap,而不是声明一个新的Map,您可以通过forEach的副作用将additionalMap合并到其中:

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

这将从additionalMap中获取每个键(k)和值(v),并使用Int::plus将其添加到originMap中的值。

英文:

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.

答案3

得分: 1

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

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

Similar to previous answer, but without JVM specific API:

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

答案4

得分: 0

以上解决方案存在一个轻微的错误,它会将所有在 additionalMap 中存在但在 originalMap 中不存在的额外键添加到结果中。
意思是下面的代码会产生如下输出:

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) }
// 输出 {Foo=14, Bar=5, Baz=3}

因此,不带有轻微错误的相同解决方案如下:

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

如果担心特定于 JVM 的 API:则相同的解决方案如下:

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

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}

</details>



huangapple
  • 本文由 发表于 2020年10月12日 01:09:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/64306839.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定