2017-10-06 9 views
0

これはちょっと混乱します。ruby​​ hashメンバーが再帰的に存在するかどうかをチェックする方法は?

ハッシュなどがあるハッシュが多い場合は、複数のレイヤーが存在するメンバーが存在するかどうかをどのように判断しますか?あなたはハッシュだけ持っている場合は、上記のハッシュに「何か」が存在を確認しに行くかどう

hash 1 = 
{ 
    "layer1" => 
    { 
     "layer2" => 
     { 
      "layer3" => ['Something', 'Array'] 
     } 
    } 
} 

:たとえば

hash2 = 
{ 
    "layer1" => 
    { 
     "layer2" => ['Other Array'] 
    } 
} 

、私がしようとするだろう。例えば

do:

if hash2['layer1']['layer2']['layer3'].contains? 'Something' 
    puts "Found Something!" 
end 

しかし、これはエラー未定義のメソッド `contains? 'なしの場合:NilClass。 layer3は存在しないため、NilClassになります。これらの埋め込まれたハッシュのうちの1つがNilであればそれが存在しないと言うだけで十分ですが、あなたが深すぎる層であればNilも返すので、それらの存在を簡単にテストできません。あなたが.nilを呼び出すときに要求する特定のメンバーの代わりに、Nilの各最上位層を再帰的にチェックする関数がルビにありますか? など。私は何がうまくいくと思いますか!

if hash2['layer1']['layer2']['layer3'].nil? 
    puts 'layer3 exists' 
end 

しかし.nil? は、 'layer3'が存在するかどうかをチェックします。 'layer1'で始まり、 'layer2'が存在し、 'layer3'などが存在するかどうかを調べるメソッドがありますか?そして、いずれの部分でもそれは偽であると返されません。 'layer2'または 'layer1'が存在しないと、定義されていないメソッド `[] 'がnil:NilClassに対してエラーとなります。

+0

https://stackoverflow.com/q/8301566/5101493助けてもらう –

答えて

1

チェックアウトHash#dig()。キー配列を再帰的に検索し、いずれかが見つからない場合はnilを返します。ドキュメントから:

h = { foo: {bar: {baz: 1}}} 

h.dig(:foo, :bar, :baz)   #=> 1 
h.dig(:foo, :zot)     #=> nil 

ちょうどbaznilだった場合、その最初の呼び出しがnilを返されたであろうことに注意してください。したがって、あなたがあなたのハッシュに格納されているnilを持っていないことを知っているならば、入れ子にされたキーが存在するかどうかをチェックするための代替えだけです。

+1

'.dig'は素晴らしいです!また、バージョン2.3以降でのみ動作することに注意してください。これが宝石や他のライブラリの中にある場合、以前のバージョンのユーザーにはうまくいかないでしょう。 – whodini9

+0

Omg、これはまさに私が探していたものです。この問題を表現する方法が非常に多くの異なるバージョンにつながる可能性があるため、これを解決するのは難しいです。 – jStaff

0

ない最善の解決策が、私はこれを書いた:

h = {"layer1"=> 
     {"layer2"=> 
      {"layer3"=>["Something", "Array"]} 
     }, 
    "layerx" => ["d"], 
    "layerz" => {"layera" => "deep"} 
} 

def vals(h) 
    return h if !h.is_a?(Hash) 
    h.values.map(&method(:vals)).flatten 
end 
vals(h) #=> ["Something", "Array", "d", "deep"] 

valsは、ハッシュ-ESの奥深くにネスト値を示します。要素がその中にあるかどうかを確認することができます。

関連する問題