読者です 読者をやめる 読者になる 読者になる

ここにタイトルが入ります

デザイン&プログラミングのことも書くし、それ以外のことも書く。

【Ruby】階層の深いHashを作る方法を知って考えてみた。

ruby

rubyでプログラムしているとhashのvalueがhash、みたいな
階層の深いハッシュを作る場合結構ありますよね。

※極端な例
{ :hoge => { :fuga => { :piyo => { :foo => { :bar => {:baz => 1 } } } } } }

ただその場合いちいちハッシュを定義するのがめんどくさい。


2階層のハッシュをいきなり定義する方法

それを楽に定義する方法が書いてありました。


〜大変参考になりました!〜
階層の深いHashを作成するときに知っておいたら便利なこと - (゚∀゚)o彡 sasata299's blog


ハッシュを定義する場合に、

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

と定義しておけば、ハッシュの値がハッシュという変数ができます☆


これはここ(Hash.newについて)を参照してもらうとわかるのですが、
ハッシュのnewメソッドには、
そのハッシュ自身と指定したキーを引数とするブロックを渡すことができ、
もしハッシュに存在しないキーが指定された場合はそのブロックが実行されます。

つまり、↑の例ではもしkという知らないキーが指定されたら、
ハッシュに k => {} となるようなkey-valueを追加するよう
指定しているわけです。
(言ってること超わかりにくくてすみません…)


…でも、この書き方だと
hash[:foo] = 1 はもちろんのこと、
hash[:foo][:bar] = 1 もできるのに、
hash[:foo][:bar][:baz]はいきなりセットできない。
 #=> NoMethodError: undefined method `[]=' for nil:NilClass

ブロックはあくまで一番外のハッシュに対してだから、3階層のhashを定義しようと思うと、

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

このように定義しなければなりません。


n階層のハッシュをいきなり定義する方法

そうすると階層の深さを気にせず書けないかな〜と思うわけですが
あるみたいですそういう書き方Σ(´∀`;)


〜大変参考になりました!〜
Ruby On Rails ピチカート街道 - rubyでハッシュのハッシュのハッシュとかを簡単に作る方法 -


こう書くと何階層でも気にせずいけるそうです!

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


これ、なんて言葉すればいいかわからないですけど、

{ |h,k| h[k] = Hash.new(&h.default_proc) }

このブロックを一番外のハッシュに渡しているわけですが、
kという知らないキーを指定されたら、その値には

Hash.new(&h.default_proc)

をセットしなさいと言っているわけです。
Hash.newに引数を渡した場合はその引数がデフォルト値になるので、
おそらく知らないキーkの値にハッシュ自身hのdefault_procである

{ |h,k| h[k] = Hash.new(&h.default_proc) }

がセットされるのではないかと。


だから何階層知らないキーが来ようが(hash[:hoge][:fuga]…[:piyo])、
ずっと値には同じdefault_procを持つ新しいhashがセットされるわけですおそらく。

default_procとは



もう理解できたんだかできてないんだかわけわからないですが、
要は

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

便利だね!ってことですな。