2017-10-06 51 views
0

這有點讓人困惑。如何檢查ruby散列成員是否遞歸存在?

如果你有一個散列,其中包含更多的散列,也有散列等,你如何確定一個成員是否存在超過一層深?

例如:

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

,你會如何去驗證「東西」存在於上述哈希如果哈希只有:

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

例如,我會嘗試做:

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

但這會錯誤未定義的方法`包含?'爲零:NilClass。其中layer3將是NilClass,因爲它不存在。如果其中一個嵌入式哈希值爲零,則表明它不存在,但您不能輕易測試它們的存在,因爲如果您的圖層太深,它也會返回Nil。在ruby中是否有一個函數以遞歸方式檢查每個頂層圖層,而不是在您要調用.nil時請求的特定成員? E.g.我認爲會起作用的!

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

但是.nil? 只有檢查'layer3'是否存在。是否有一種方法從'layer1'開始,然後檢查'layer2'是否存在,然後是'layer3'等等。在任何部分都是零,它返回false?因爲如果'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值。你可以檢查你的元素是否在那裏。

相關問題