34

Rubyでハッシュのハッシュを作成すると、便利な2次元(またはそれ以上)のルックアップが可能になります。ただし、挿入するときは、最初のインデックスがハッシュにすでに存在するかどうかを常に確認する必要があります。例えば:

h = Hash.new
h['x'] = Hash.new if not h.key?('x')
h['x']['y'] = value_to_insert

新しいハッシュが自動的に作成される場合は、次のことを行うことをお勧めします。

h = Hash.new
h['x']['y'] = value_to_insert

同様に、最初のインデックスがまだ存在しない値を検索する場合は、「[]」エラーの未定義のメソッドを受け取るよりも、nilが返される方が望ましいでしょう。

looked_up_value = h['w']['z']

この動作をするHashラッパークラスを作成することもできますが、このタスクを実行するための既存のRubyイディオムはありますか?

4

2 に答える 2

54

Hash.newクエリされた値がまだ存在しない場合にデフォルト値を生成するために実行されるブロックを関数に渡すことができます。

h = Hash.new { |h, k| h[k] = Hash.new }

もちろん、これは再帰的に行うことができます。詳細を説明する記事があります。

完全を期すために、任意の深さのハッシュに関する記事の解決策を次に示します。

hash = Hash.new(&(p = lambda{|h, k| h[k] = Hash.new(&p)}))

この解決策を最初に思いついたのはKentSibilevです。

于 2008-10-04T12:16:03.567 に答える
4

自己活性化と呼ばれるものは、祝福であると同時に呪いでもあります。問題は、値が定義される前に値を「見る」と、スロット内のこの空のハッシュで立ち往生し、後でそれを削除する必要があることです。

少しの混乱を気にしない場合は、いつでもor-equalsスタイルの宣言を詰め込むことができます。これにより、クエリを実行したときに期待される構造を構築できます。

((h ||= { })['w'] ||= { })['z']
于 2009-04-11T04:24:11.143 に答える