2017-10-06 62 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值。你可以检查你的元素是否在那里。

相关问题