ruby で 多次元hash の初期化するときの話
each の中とかで、いきなり
h["1"]["2"] = 2
とかやりたいときの話。 Hash.new して上記のようなことをやろうとすると、エラーになってしまう。
rakkyooの備忘録 では以下のような書き方があるよーと紹介されている。
# 2次元ハッシュの初期化 h = Hash.new { |hash,key| hash[key] = Hash.new {} } # 3次元ハッシュの初期化 h = Hash.new { |hash,key| hash[key] = Hash.new { |hash,key| hash[key] = {} } } h["1"]["2"]["3"] = 3 # (=> エラーになりません.)
でもこれ、ちとわかりづらい。ただ初期化するだけなのにとても長い。
こんなやり方があります。
#2次元ハッシュの初期化 h = Hash.new( {} ) # Hash#new に空配列を渡す #3次元ハッシュの初期化 h = Hash.new( Hash.new( {} ) ) # Hash.new したものに、さらに二次元で初期化された hash を渡す h["1"]["2"]["3"] = 3 # (=> エラーになりません.)
おまけ
別の話になるけれど、初期化せずに以下のように小分けにする方法も合ったりする。
初期化にこだわるのではなく、こちらのやり方で書いてみると、意外とコードがスッキリするときもあるので、メモ。
hash = { } h = { "2" => 2 } hash["1"] = h hash["1"]["2"] #=> 2
応用例
hash = {}.tap do |h| h["1"] = { "2" => 2 } end hash["1"]["2"] #=> 2