Nice way to add number to element in Scala map if key exists or insert new element it not
The shortest way to do that:
a += a.get(key).map(x => key -> (x + 5)).getOrElse("k5" -> 200)
In general:
a += a.get(k).map(f).map(k -> _).getOrElse(kv)
Same if your dictionary is immutable:
m + m.get(k).map(f).map(k -> _).getOrElse(kv)
so I don't see any reason to use mutable collection here.
If you don't like all these Option.map
things:
m + (if (m.contains(k)) k -> f(m(k)) else kv)
Note, that there is a whole class of possible variations:
k1 -> f(m(k1)) else k2 -> v2 //original
k1 -> f(m(k1)) else k1 -> v2
k1 -> f(m(k2)) else k2 -> v2
k1 -> f(m(k2)) else k1 -> v2
k2 -> v2 else k1 -> f(m(k1))
k1 -> v2 else k1 -> f(m(k1))
k2 -> v2 else k1 -> f(m(k2))
k1 -> v2 else k1 -> f(m(k2))
... //v2 may also be a function from some key's value
So, Why it's not a standard function? IMO, because all variations still can be implemented as one-liners. If you want library with all functions, that can be implemented as one-liners, you know, it's Scalaz :).
P.S. If yu also wonder why there is no "update(d) if persist" function - see @Rex Kerr 's answer here
You can create you own function for that purpose:
def addOrUpdate[K, V](m: collection.mutable.Map[K, V], k: K, kv: (K, V),
f: V => V) {
m.get(k) match {
case Some(e) => m.update(k, f(e))
case None => m += kv
}
}
addOrUpdate(a, "k1", "k5" -> 200, (v: Int) => v + 5)
Scala 2.13 introduced updatedWith
method which seems to be the most idiomatic way to update a map conditionally on the existence of the key.
val a = Map(("k1" -> 1), ("k2" -> 5))
val a1 = a.updatedWith("k1") {
case Some(v) => Some(v + 5)
case None => Some(200)
}
println(a1) // Map(k1 -> 6, k2 -> 5)
One may also remove values using it:
val a2 = a.updatedWith("k2") {
case Some(5) => None
case v => v
}
println(a2) // Map(k1 -> 1)
An excerpt from the Scala Standard Library reference:
def updatedWith[V1 >: V](key: K)(remappingFunction: (Option[V]) => Option[V1]): Map[K, V1]Update a mapping for the specified key and its current optionally-mapped value (
Some
if there is current mapping,None
if not).If the remapping function returns
Some(v)
, the mapping is updated with the new valuev
. If the remapping function returnsNone
, the mapping is removed (or remains absent if initially absent). If the function itself throws an exception, the exception is rethrown, and the current mapping is left unchanged.