如何检查ruby散列成员是否递归存在?

时间:2017-10-06 16:08:55

标签: ruby hash null

这有点令人困惑。

如果你的哈希包含更多具有哈希值的哈希值,那么你如何确定一个成员是否存在多个深层?

例如:

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

如果哈希只有以下内容,您将如何验证' Something' 是否存在:

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

例如,我会尝试:

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

但这会错误未定义的方法`包含?'为零:NilClass 。其中layer3将是NilClass,因为它不存在。如果这些嵌入的散列中的一个是Nil然后说它不存在就足够了,但你不能轻易地测试它们的存在,因为如果你的层太深,它也将返回Nil。在ruby中是否有一个函数以递归方式检查每个顶级层的Nil,而不是在调用.nil时请求的特定成员?的 E.g。我认为会起作用!

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

但是.nil? 检查' layer3'存在。有没有一种方法,从第1层开始,'层1'然后检查是否'第2层'然后存在'第3层'等等。并且在任何部分都是零,它返回false?因为如果' layer2'或者' layer1'没有它会错误地说未定义的方法`[]'为零:NilClass。

2 个答案:

答案 0 :(得分:2)

结帐Hash#dig()。它需要一组键并以递归方式查找它们,如果缺少任何键,则返回nil。来自文档:

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

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

请注意,如果baznil,则首次dig来电将返回nil。因此,如果您知道自己的哈希值中没有nil存储,那么它只是检查嵌套密钥是否存在的替代品。

答案 1 :(得分: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给出嵌套在hash-es内部的值。你可以检查你的元素是否存在。