マップ | 目次 |
マップ(Map)はキーと値のペアからなるIterableです(写像や関連付けとも言います)。 ScalaのPredefはペア(key, value)の代わりの構文としてkey -> valueと書けるようにする暗黙の変換を提供します。 例えば、Map("x" -> 24, "y" -> 25, "z" -> 26)はMap(("x", 24), ("y", 25), ("z", 26))と全く同じ結果となりますが、より読みやすくなります。
マップへの基本的な演算は集合のものに似ています。 基本的な演算は以下の表に要約でき、以下のカテゴリに分類できます:
です。def get(key): Option[Value]
演算"m get key"はマップが与えられたキーに対する関連付けを含むか調べます。もしそうならば関連付けられた値をSomeで包んで返します。 もしkeyがマップで定義されていなければgetはNoneを返します。 またマップは与えられたキーに関連付けられた値をOptionで包まずに直接返すapplyも定義しています。 もしキーがマップの中で定義されていなければ例外が投げられます。
何であるか | 何をするか |
---|---|
参照: | |
ms get k | マップmsでキーkと関連付けられた値をオプション値としたもの。見付からなければNone。 |
ms(k) | (または書き下してms apply k) マップmsでキーkと関連付けられた値。見付からなければ例外。 |
ms getOrElse (k, d) | マップmsでキーkと関連付けられた値。見付からなければデフォルト値d。 |
ms contains k | msがキーkに対する関連付けを含むかテストする。 |
ms isDefinedAt k | containsと同じ。 |
追加と更新: | |
ms + (k -> v) | msの全ての関連付けと、キーkから値vへの関連付けk -> vを含むマップ。 |
ms + (k -> v, l -> w) | msの全ての関連付けと、与えられたキーと値のペアを含むマップ。 |
ms ++ kvs | msの全ての関連付けと、kvsの全てのキーと値のペアを含むマップ。 |
ms updated (k, v) | ms + (k -> v)と同じ。 |
削除: | |
ms - k | msの全ての関連付けからキーkに対する関連付けを除いたマップ。 |
ms - (k, l, m) | msの全ての関連付けから与えられたキーに対する関連付けを除いたマップ。 |
ms -- ks | msの全ての関連付けからks内の任意のキーに対する関連付けを除いたマップ。 |
部分コレクション: | |
ms.keys | ms内の各キーを含むイテラブル。 |
ms.keySet | ms内の各キーを含む集合。 |
ms.keysIterator | ms内の各キーを返すイテレータ。 |
ms.values | ms内でキーと関連付けられた各値を含むイテラブル。 |
ms.valuesIterator | ms内でキーと関連付けられた各値を返すイテレータ。 |
変換: | |
ms filterKeys p | ms内の関連付けでキーが述語pを満たすもののみを含むマップのビュー(訳註: ここで言うビューとは後で説明するビューとは異なり、フィルタリングのみを遅延的に評価し、その他の演算は遅延的に扱わない。mapValuesも同様)。 |
ms mapValues f | ms内のキーに関連付けられた各値に関数fを適用してできたマップのビュー。 |
可変なマップはさらに以下の表に要約できるメソッドを提供します。
何であるか | 何をするか |
---|---|
追加と更新: | |
ms(k) = v | (または書き下してms.update(x, v))。 マップmsにキーkから値vへの関連付けを副作用として追加し、既存のkの関連付けを上書きする。 |
ms += (k -> v) | マップmsにキーkから値vへの関連付けを副作用として追加し、ms自身を返す。 |
ms += (k -> v, l -> w) | マップmsに与えられた関連付けを副作用として追加し、ms自身を返す。 |
ms ++= kvs | マップmsにkvsの全ての関連付けを副作用として追加し、ms自身を返す。 |
ms put (k, v) | マップmsにキーkから値vへの関連付けを副作用として追加し、以前kと関連付けられていた値をオプション値として返す。 |
ms getOrElseUpdate (k, d) | もしキーkがマップmsで定義されていれば、その関連付けられた値を返す。 そうでなければmsを関連付けk -> dで更新し、dを返す。 |
削除: | |
ms -= k | マップmsからキーkに対する関連付けを副作用として取り除き、ms自身を返す。 |
ms -= (k, l, m) | マップmsから与えられたキーに対する関連付けを副作用として取り除き、ms自身を返す。 |
ms --= ks | マップmsからks内の全てのキーを副作用として取り除き、ms自身を返す。 |
ms remove k | msからkに対する関連付けを取り除き、kと関連付けられていた値をオプション値として返す。 |
ms retain p | ms内に述語pを満たすキーを持つ関連付けのみを残す。 |
ms.clear() | msから全ての関連付けを取り除く。 |
変換: | |
ms transform f | ms内の全ての関連付けられた値を関数fで変換する。 |
複製: | |
ms.clone | msと同じ関連付けを持つ新しい可変なマップを返す。 |
マップの追加と削除演算は集合のものとよく似ています。 集合のように、可変なマップは非破壊的な追加演算+, -, およびupdatedをサポートしますが、それらは可変なマップのコピーを伴うためあまり使われません。 代わりに可変なマップmは通常m(key) = valueやm += (key -> value)といった2つの変種により「直接」変更されます。 m put (key, value)という変種もあり、keyに以前関連付けられていた値を含むOptionか、もし以前マップにkeyが存在しなければNoneを返します。
getOrElseUpdateはキャッシュとしてふるまうマップにアクセスする場合に便利です。 fで引き起こされる高価な演算があるとします:
scala> def f(x: String) = {
println("taking my time."); sleep(100)
x.reverse }
f: (x: String)String
さらにfは副作用を伴わず、同じ引数で呼び出すと常に同じ結果を返すとします。 この場合、以前に計算したfの引数と値の束縛をマップに保持しておき、引数の結果がそこに見付からない場合にのみfを計算するようにして時間を節約できます。 この場合マップは関数fの計算のキャッシュであると言えます。
val cache = collection.mutable.Map[String, String]()
cache: scala.collection.mutable.Map[String,String] = Map()
ここでキャッシュを使うfのより効率的なバージョンを作成できます:
scala> def cachedF(s: String) = cache.getOrElseUpdate(s, f(s))
cachedF: (s: String)String
scala> cachedF("abc")
taking my time.
res3: String = cba
scala> cachedF("abc")
res4: String = cba
getOrElseUpdateの第2引数は「名前呼び」であり、f("abc")の計算はgetOrElseUpdateがその第2引数の値を必要とする場合、正確には最初の引数がマップcacheに無い場合にのみ実行される点に注意してください。 cachedFは直接基本的なマップ演算のみを使って実装できますが、より多くのコードが必要です:
def cachedF(arg: String) = cache get arg match {
case Some(result) => result
case None =>
val result = f(x)
cache(arg) = result
result
}
続いては:
マップ | 目次 |