4

ハッシュ初期化子:

# this
animals = Hash.new { [] }
animals[:dogs] << :Scooby
animals[:dogs] << :Scrappy
animals[:dogs] << :DynoMutt
animals[:squirrels] << :Rocket
animals[:squirrels] << :Secret
animals #=> {}
# is not the same as this
animals = Hash.new { |_animals, type| _animals[type] = [] }
animals[:dogs] << :Scooby
animals[:dogs] << :Scrappy
animals[:dogs] << :DynoMutt
animals[:squirrels] << :Rocket
animals[:squirrels] << :Secret
animals #=> {:squirrels=>[:Rocket, :Secret], :dogs=>[:Scooby, :Scrappy, :DynoMutt]}

誰かが別の質問にこれらを投稿しているのを見ましたが、最初のケースで動物が空白に見える理由がわかりません。入力すると

animals[:dogs]

適切な配列を取得します。

4

3 に答える 3

7

最初の形式は、見つからないキーのデフォルト値を返すブロックを指定します。つまり、 を呼び出すと、ハッシュにキーanimals[:dogs]がないため、ブロックが呼び出され、ブロックの結果、つまり. 次に何が起こるかというと、それがその空のリストに追加され、喜んで破棄されます。:dogsanimals[:dogs][]<< :Scooby:Scooby

2 番目の形式は、キーが要求されて見つからない場合に、ハッシュ自体と見つからなかったキーをパラメーターとして受け取るブロックを指定します。これは、最初のコンストラクターのわずかに強力なバージョンです。違いは、ブロックの機能にあります。この 2 番目の形式では、ハッシュを変更[]して、まだ見つかっていないキーに関連付けます。そのため、ハッシュ内に保存され、<< :Scoobyそこに保存され:Scoobyます。ハッシュに存在するため、それ以降の呼び出し:dogはブロックをトリガーしません。:dog

于 2012-03-02T00:22:35.360 に答える
3

最初のケースでは、キーが存在しない場合に返されるデフォルト値は です[]。その後、さまざまなステートメントによって、返された配列にさまざまな犬やリスが正常に追加されます。

ただし、これまでに作成されたキーはありません:dogs:squirrels.

2 番目のケースでは、ブロックキーを使用して新しい値をハッシュ エントリに格納します。

ここで興味深いのは、最初のケースで新しい空の配列を取得し続ける方法です。答えは次のとおりです[]。パラメーターとしてではなく、ブロックとして渡しました。これは実行可能で、proc として保存されます。キーが見つからないたびに、proc が再度実行され、新しい[].

これを操作で確認できます。異なるオブジェクト ID 値に注意してください。

irb > t = Hash.new { [] }
 => {} 
irb > t[:a].object_id
 => 2149202180 
irb > t[:a].object_id
 => 2149192500 
于 2012-03-02T00:25:23.683 に答える
0

最初が失敗し、2 番目が失敗する理由は、Hash.new に渡されるブロックのためです。

このブロックは、まだ存在しないキーにアクセスしたときに返されるデフォルトの型を定義するのに役立ちます。最初の例では、エントリ初期化子がないため、新しいキーごとに{}、または空のが返されますHash。Hash には method がない<<ため、何も返しません。

2 番目のケースは、エントリ初期化子が空の として定義されているため、正しく機能しますArray。したがって、この場合、animals[:dogs]初めてアクセスすると[]、空Arrayの代わりに{}空のが返されますHash。Array には というメソッドがある<<ため、正常に機能し、指定されたキーでシンボルを配列にシャベルします。

これで解決することを願っています。

于 2012-03-02T00:20:23.613 に答える