如何递归检查ruby hash成员是不是存在?

Posted

技术标签:

【中文标题】如何递归检查ruby hash成员是不是存在?【英文标题】:How to check if ruby hash member exists recursively?如何递归检查ruby hash成员是否存在? 【发布时间】:2018-03-18 12:02:46 【问题描述】:

这有点令人困惑。

如果你有一个哈希包含更多的哈希也有哈希等等,你如何确定一个成员是否存在超过一层深度?

例如:

hash 1 =

    "layer1" => 
    
        "layer2" => 
        
            "layer3" => ['Something', 'Array']
        
    

如果哈希只有:

,您将如何验证上述哈希中是否存在 'Something'
hash2 =

    "layer1" => 
    
        "layer2" => ['Other Array']
    

例如,我会尝试这样做:

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

但这会报错未定义的方法“包含?”对于 nil:NilClass。其中 layer3 将是 NilClass 因为它不存在。如果这些嵌入的哈希值之一是 Nil 就足够了,然后说它不存在,但你不能轻易测试它们的存在,因为如果你的层太深,这也会返回 Nil。 ruby 中是否有一个函数可以递归地检查每个顶层的 Nil,而不是在调用 .nil 时请求的特定成员? 例如我认为可行的方法!

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

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

【问题讨论】:

***.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,则第一个dig 调用将返回nil。因此,如果您知道不会将 nils 存储在哈希中,则它只是检查是否存在嵌套键的替代品。

【讨论】:

.dig 太棒了!另请记住,它仅适用于 2.3+ 版本。如果这是在 gem 或其他库中,它将不适用于以前版本的用户。 天啊,这正是我想要的。很难找到这个问题的解决方案,因为这个问题的表述方式可能会导致很多不同的版本。【参考方案2】:

不是最好的解决方案,但我写了这个:

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 给出嵌套在哈希内部深处的值。你可以检查你的元素是否在那里。

【讨论】:

以上是关于如何递归检查ruby hash成员是不是存在?的主要内容,如果未能解决你的问题,请参考以下文章

Ruby Style:如何检查嵌套的哈希元素是不是存在

Ruby Style:如何检查嵌套的哈希元素是不是存在

如何检查具有特定角色的成员是不是存在于 discord.js 的特定语音通道中

如何检查哈希中是不是存在特定键?

如何检查给定网址中是不是存在图像?

如何检查Ruby中是否已存在类