例として、以下のような深いハッシュがあるとします
> x = {a: {b: {c: 1}}}
=> {:a=>{:b=>{:c=>1}}}
このハッシュに対して、 x[:a][:b][:d]
が存在するかどうかを判定したいです
直感的に、以下のようにすれば判定できそうです
> x[:a][:b][:d]
=> nil
結果は nil
が返ってきたので期待通りです。
では、次に x[:a][:e][:f]
が存在するか判定します
上と同様に
> x[:a][:e][:f]
としてみます
しかし、ここで問題が発生します
x[:a][:e]
が nil
なので、それに続けて[:f]
を評価することができず、エラーが返ってきます
> x[:a][:e][:f]
Traceback (most recent call last):
4: from /usr/bin/irb:23:in `<main>'
3: from /usr/bin/irb:23:in `load'
2: from /Library/Ruby/Gems/2.6.0/gems/irb-1.0.0/exe/irb:11:in `<top (required)>'
1: from (irb):3
NoMethodError (undefined method `[]' for nil:NilClass)
このエラーを回避するためには、以下のようにして要素をひとつひとつ nil
か否かを判定する必要があります
> x[:a] && x[:a][:e] && x[:a][:e][:f]
=> nil
hash.dig() を使う
上記の方法では、判定式が長くなってしまい可読性が低くなります
そこで、 x[:a] && x[:a][:e] && x[:a][:e][:f]
をもっと簡単に書ける関数 dig
を使います
> x.dig(:a,:e,:f)
=> nil
これで、 nil
が返ってきます
参考