Ruby 风格:如何检查嵌套的哈希元素是否存在 [英] Ruby Style: How to check whether a nested hash element exists
问题描述
考虑一个存储在散列中的人".两个例子是:
Consider a "person" stored in a hash. Two examples are:
fred = {:person => {:name => "Fred", :spouse => "Wilma", :children => {:child => {:name => "Pebbles"}}}}
slate = {:person => {:name => "Mr. Slate", :spouse => "Mrs. Slate"}}
如果person"没有任何孩子,则children"元素不存在.所以,对于 Slate 先生,我们可以检查他是否有父母:
If the "person" doesn't have any children, the "children" element is not present. So, for Mr. Slate, we can check whether he has parents:
slate_has_children = !slate[:person][:children].nil?
那么,如果我们不知道slate"是一个person"哈希怎么办?考虑:
So, what if we don't know that "slate" is a "person" hash? Consider:
dino = {:pet => {:name => "Dino"}}
我们不能再轻易地检查孩子:
We can't easily check for children any longer:
dino_has_children = !dino[:person][:children].nil?
NoMethodError: undefined method `[]' for nil:NilClass
那么,您将如何检查散列的结构,尤其是如果它嵌套很深(甚至比此处提供的示例更深)?也许更好的问题是:什么是Ruby 方式"来做到这一点?
So, how would you check the structure of a hash, especially if it is nested deeply (even deeper than the examples provided here)? Maybe a better question is: What's the "Ruby way" to do this?
推荐答案
最明显的方法是简单地检查每一步:
The most obvious way to do this is to simply check each step of the way:
has_children = slate[:person] && slate[:person][:children]
.nil 的使用?仅当您使用 false 作为占位符值时才真正需要它,实际上这种情况很少见.通常,您可以简单地测试它是否存在.
Use of .nil? is really only required when you use false as a placeholder value, and in practice this is rare. Generally you can simply test it exists.
更新:如果您使用的是 Ruby 2.3 或更高版本,则有一个内置的 dig
方法,该方法执行此答案中描述的操作.
Update: If you're using Ruby 2.3 or later there's a built-in
dig
method that does what's described in this answer.
如果没有,您也可以定义自己的哈希挖掘"方法,这可以大大简化:
If not, you can also define your own Hash "dig" method which can simplify this substantially:
class Hash
def dig(*path)
path.inject(self) do |location, key|
location.respond_to?(:keys) ? location[key] : nil
end
end
end
这个方法会检查每一步,避免调用 nil 时出错.对于浅层结构,实用性有限,但对于深度嵌套的结构,我发现它是无价的:
This method will check each step of the way and avoid tripping up on calls to nil. For shallow structures the utility is somewhat limited, but for deeply nested structures I find it's invaluable:
has_children = slate.dig(:person, :children)
您还可以使这更加健壮,例如,测试 :children 条目是否实际填充:
You might also make this more robust, for example, testing if the :children entry is actually populated:
children = slate.dig(:person, :children)
has_children = children && !children.empty?
这篇关于Ruby 风格:如何检查嵌套的哈希元素是否存在的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!