scala immutable.Map 的惯用“获取或更新”?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4385976/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 02:37:30  来源:igfitidea点击:

idiomatic "get or else update" for immutable.Map?

scalascala-collections

提问by IttayD

What is the idiomatic way of a getOrElseUpdate for immutable.Map instances?. I use the snippet below, but it seems verbose and inefficient

immutable.Map 实例的 getOrElseUpdate 的惯用方式是什么?我使用下面的代码段,但它似乎冗长且效率低下

var map = Map[Key, Value]()

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

采纳答案by Debilski

Let me summarise your problem:

我总结一下你的问题:

  • You want to call a method on a immutable data structure
  • You want it to return some value andreassign a var
  • Because the data structure is immutable, you'll need to
    • return a new immutable data structure, or
    • do the assignment inside the method, using a supplied closure
  • 您想在不可变数据结构上调用方法
  • 您希望它返回一些值重新分配一个var
  • 因为数据结构是不可变的,所以你需要
    • 返回一个新的不可变数据结构,或
    • 使用提供的闭包在方法内部进行赋值

So, either your signature has to look like

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

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

or

或者

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

If you can live with one of these solutions, you could add your own version with an implicit conversion but judging by the signatures alone, i wouldn't think any of these is in the standard library.

如果您可以接受这些解决方案之一,您可以添加您自己的带有隐式转换的版本,但仅从签名来看,我认为这些都不会出现在标准库中。

回答by Frank S. Thomas

I would probably implement a getOrElseUpdatedmethod like this:

我可能会实现这样的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)
  }

which either returns the original map if mhas a mapping for keyor another map with the mapping key -> opadded. The definition of this method is similar to getOrElseUpdateof mutable.Map.

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

回答by Vasil Remeniuk

There's no such way - map mutation (update), when you're getting a map value, is a side effect (which contradicts to immutability/functional style of programming).

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

When you want to make a new immutable map with the default value, if another value for the specified key doesn't exist, you can do the following:

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

map + (key -> map.getOrElse(key, new Value)) 

回答by Daniel C. Sobral

Why not use withDefaultor withDefaultValueif you have an immutable map?

为什么不使用withDefault或者withDefaultValue如果你有一个不可变的地图?