質問

I need to update (retrieve and increase) two different values bound to two keys in a map. The two keys can coincide sometimes. I have the following code for now:

// 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)))
}

As you can see, if you use the else block when key1 == key2, then the value at key1 == key2 will incorrectly be increased by 1 instead of 2 --- the second tuple erroneously updates the original value, rather than the value applied by the first tuple.
Is there a cleaner way to write this?

役に立ちましたか?

解決

First of all, you can simplify the map to return 0 when no key is present:

val map0 = Map.empty[Int, Int] withDefaultValue 0

Then you can safely call map(key) instead of map.getOrElse(key, 0).

Second, you can use the arrow-association syntax to create Tuple2 instances. I.e. key -> value instead of Tuple2(key, value).

Third, I would not introduce the if ... then ... else at all. Just update the map for each key successively:

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)

他のヒント

Another SO Answer suggests using the Monoid characteristics of Map (ScalaZ):

tailRecFunction(someArg, map |+| Map(key1 -> 1) |+| Map(key2 -> 1))

The |+| operator will sum values that belong to the same key.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top