【问题标题】:Put if absent to map in scala如果不存在则在 scala 中映射
【发布时间】:2018-02-08 11:20:39
【问题描述】:

我有以下地图:

val m: mutable.Map[String, Long] = mutable.Map()

如果它不存在,我想给它一些价值。如果它依次存在,我想执行一些计算:

目前我的做法如下:

val key: String = //...
val value: Long = //...
m(key) = m.getOrElse(key, 0L) + value

但这对我来说有点冗长(在 Java 中我们有 putIfAbsent 方法)。在 Scala 中是否有更短的方法?

【问题讨论】:

  • 问题的标题和内容指向一个典型的 XY 问题。当您尝试解决实际问题时,您发现您不需要标题中要求的内容...因此,也许您应该将标题更新为“如果缺少值,则更新默认值在地图中(在 Scala 中)”,或类似的东西。

标签: scala collections


【解决方案1】:

对于mutable maps,您可以覆盖default 方法,或使用withDefault 添加默认计算,以便在首次访问时自动计算所有缺失值:

val m = new HashMap[String, Int].withDefault(k => 0)

然后你可以像这样更新值:

m("foo") += 5
m("bar") += 7
m("foo") += 37

println(m) // Map(foo -> 42, bar -> 7)

【讨论】:

  • 所以没有类似putIfAbsent...?
  • withDefault 类似于自动触发的putIfAbsent。每次访问新密钥时都会自动调用它。
  • @St.Antario 如果你真的想要正是putIfAbsent的功能,你确实可以使用getOrElseUpdate,然后忽略返回值。因此,在某种程度上,Yuval Itzchakov 从字面上回答了您在括号中关于 Java 方法的类比问题的部分。我只是不明白它应该如何帮助您解决如何使“获取和更新”更短的实际问题。如果您使用getOrElseUpdate 而不是getOrElse,您的代码会变得更长并且性能会稍微降低(因为额外的写入)。这不是Java。用 Scala 写出有效的东西。
  • 仍然不明白getOrElseUpdate 有什么帮助...它设置了新值而不考虑前一个值。 ideone.com/SLbuex
  • @St.Antario : withDefaultValue 在这种情况下也会更快。 Java 中没有类似的东西,因为命令式的 do-it-right-now putDefaultValueToAllAbsentKeys 必须为无限多的键放置一个 0,这显然是行不通的。
【解决方案2】:

你正在寻找mutable.Map.getOrElseUpdate:

m.getOrElseUpdate(key, value)

【讨论】:

  • 虽然这肯定是一种非常方便的方法,但我看不出它在这个特定的用例中会有什么帮助。不是只会使分配恰好长 6 个字符,并且每个键都需要一个额外的 put(0) 一次吗?
  • 刚刚试了下,没有达到我的预期。 demo。我期待key -> 50L,但key -> 20L 是。
猜你喜欢
  • 2013-08-26
  • 2014-06-19
  • 2020-10-28
  • 2022-12-05
  • 2016-05-20
  • 1970-01-01
  • 2019-11-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多