8

マップ内の既存の値を更新するエレガントな方法はありますか?

これは怖すぎるように見えます:

val a = map.get ( something ) 
if ( a != null ) // case .. excuse my old language
   a.apply( updateFunction )
else 
   map.put ( something, default )
4

3 に答える 3

11

ほとんどの場合、作成時に更新できるものを挿入できます(たとえば、カウントの場合は、1を入力するだけでなく、0を入力してから1に更新します)。その場合、

map.getOrElseUpdate(something, default).apply(updateFunction)

このように整理できないというまれなケースでは、

map(something) = map.get(something).map(updateFunction).getOrElse(default)

(ただし、something2回参照する必要があります)。

于 2013-01-25T20:04:48.047 に答える
3

これは私が通常書いているものです...より良い解決策があるかどうかはわかりません。

map.get(key) match {
  case None => map.put(key, defaultValue)
  case Some(v) => map(key) = updatedValue
}

実際update、 とputは変更可能なマップと同じですが、読みやすくするために、通常はupdate既存のエントリとput新しいエントリに使用します。

もう1つのことは、キーの存在を確認せずに最終的な値が何であるかを把握できる場合はmap(key) = value、 , at と書くだけで、エントリが自動的に作成/置換されることです。

最後に、ステートメント likemap(key) += 1は実際に機能しMap(これは通常、関数を含むコレクションに当てはまりupdateます)、多くの単純な数値演算も同様です。\


二重プットを解決するには、不変値の代わりに可変オブジェクトを使用します。

class ValueStore(var value: ValueType)
val map = new Map[KeyType, ValueStore]
...
map.get(key) match {
  case None => map.put(key, new ValueStore(defaultValue))
  case Some(v) => v.value = updatedValue
}

コメントで述べたように、の基礎となる構造は でHashMapありHashTable、実際にはこの変更可能なラッパー クラス アプローチを使用します。HashMapはより優れたラップアップ クラスですが、重複した計算を行う必要がある場合もあります。

于 2013-01-25T19:09:26.973 に答える
0

私は愚かです、あなたは(まったく)正しいです:

map.get(key) match {
  case None => map.put(key, defaultValue)
  case Some(v) => v.apply(updateFunction) // changes state of value
}

ありがとう

于 2013-01-25T19:35:52.917 に答える