在 scala.immutable.Map 中更新多个值的惯用方法
Posted
技术标签:
【中文标题】在 scala.immutable.Map 中更新多个值的惯用方法【英文标题】:Idiomatic way to update multiple values in scala.immutable.Map 【发布时间】:2014-03-26 18:02:47 【问题描述】:我需要更新(检索和增加)绑定到映射中两个键的两个不同值。这两个键有时会重合。 我现在有以下代码:
// val map: Map[Int, Int]
// val key1, key2: Int
if (key1 == key2)
tailRecFunction(someArg, map
+ Tuple2(key1, 2 + map.getOrElse(key1, 0)))
else
tailRecFunction(someArg, map
+ Tuple2(key1, 1 + map.getOrElse(key1, 0))
+ Tuple2(key2, 1 + map.getOrElse(key2, 0)))
如你所见,如果你在key1 == key2
时使用else
块,那么key1 == key2
的值将错误地增加1
而不是2
--- 第二个元组错误地更新原始值,而不是第一个元组应用的值。有没有更简洁的写法?
【问题讨论】:
为什么会被否决?请说明原因,以便我知道我在哪里犯了错误! 这个问题应该链接到Idiomatic way to update value in a Map based on previous value 【参考方案1】:首先,您可以简化映射以在不存在键时返回0
:
val map0 = Map.empty[Int, Int] withDefaultValue 0
那么您可以放心地调用map(key)
而不是map.getOrElse(key, 0)
。
其次,您可以使用箭头关联语法来创建Tuple2
实例。 IE。 key -> value
而不是 Tuple2(key, value)
。
第三,我根本不会介绍if ... then ... else
。只需连续更新每个键的映射:
def addKey(map: Map[Int, Int], key: Int) = map + (key -> (map(key) + 1))
val map1 = addKey(map0, key1)
val map2 = addKey(map1, key2)
tailRecFunction(someArg, map2)
【讨论】:
谢谢,很好的建议! (Ad3):我仍然可以避免使用val newMap = addKey(addKey(oldMap, key1), key2)
进行 val 定义
我强烈建议不要以这种方式使用withDefaultValue
,尤其是对于不可变映射。这是 scala 集合库中的缺陷之一。请参阅编译器开发人员groups.google.com/forum/#!topic/scala-internals/R4fTU_5XVZs/… 之间的这场辩论。例如,gist.github.com/drstevens/9201268
@drstevens 在直方图和计数元素的情况下,withDefaultValue(0)
是非常明智的 IMO,但是是的,您在转换地图时应该小心。
另一个SO answer 建议使用ScalaZ 库中的~
运算符,这样可以避免withDefaultValue
的危险。【参考方案2】:
另一个SO Answer 建议使用 Map (ScalaZ) 的 Monoid 特性:
tailRecFunction(someArg, map |+| Map(key1 -> 1) |+| Map(key2 -> 1))
|+|
运算符将对属于同一键的值求和。
【讨论】:
原理与Best way to merge two maps and sum the values of same key?类似以上是关于在 scala.immutable.Map 中更新多个值的惯用方法的主要内容,如果未能解决你的问题,请参考以下文章
在 CoreData 中更新项目后,项目不会在 UI 中更新
我们可以在 mongodb 中更新/更新记录吗?数据源是kafka
离子v3在应用程序中进行制造和更新,以更新它在数据库中而不是在应用程序中正在更新的数据