immutable.Map的惯用"get or else update"?

Itt*_*ayD 17 scala scala-collections

对于immutable.Map实例,getOrElseUpdate的惯用方法是什么?我使用下面的代码片段,但它似乎冗长而低效

var map = Map[Key, Value]()

def foo(key: Key) = {
  val value = map.getOrElse(key, new Value)
  map += key -> value
  value
}
Run Code Online (Sandbox Code Playgroud)

Fra*_*mas 13

我可能会实现这样的getOrElseUpdated方法:

def getOrElseUpdated[K, V](m: Map[K, V], key: K, op: => V): (Map[K, V], V) =
  m.get(key) match {
    case Some(value) => (m, value)
    case None => val newval = op; (m.updated(key, newval), newval)
  }
Run Code Online (Sandbox Code Playgroud)

如果m有映射,则返回原始地图;如果添加了映射,则返回key另一个地图key -> op.这种方法的定义类似于getOrElseUpdatemutable.Map.


Deb*_*ski 9

让我总结一下你的问题:

  • 您想要在不可变数据结构上调用方法
  • 你希望它返回一些值重新分配var
  • 因为数据结构是不可变的,所以你需要
    • 返回一个新的不可变数据结构,或
    • 使用提供的闭包在方法内部进行赋值

所以,要么你的签名看起来像

def getOrElseUpdate(key: K): Tuple2[V, Map[K,V]]
//... use it like
val (v, m2) = getOrElseUpdate(k)
map = m2
Run Code Online (Sandbox Code Playgroud)

要么

def getOrElseUpdate(key: K, setter: (Map[K,V]) => Unit): V
//... use it like
val v = getOrElseUpdate(k, map = _)
Run Code Online (Sandbox Code Playgroud)

如果您可以使用其中一种解决方案,您可以使用隐式转换添加自己的版本,但仅通过签名判断,我认为这些都不在标准库中.


Vas*_*iuk 8

没有这样的方法 - 当您获得地图值时,地图变异(更新)是副作用(与编程的不变性/功能样式相矛盾).

如果要使用默认值创建新的不可变映射,如果指定键的另一个值不存在,则可以执行以下操作:

map + (key -> map.getOrElse(key, new Value)) 
Run Code Online (Sandbox Code Playgroud)