Ruby Style:如何检查是否存在嵌套的哈希元素 [英] Ruby Style: How to check whether a nested hash element exists

查看:107
本文介绍了Ruby Style:如何检查是否存在嵌套的哈希元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑存储在哈希中的人。两个示例是:

  fred = {:person => {:name => Fred,:spouse => Wilma,:children => {:child => {:name => Pebbles}}}} 
slate = {:person => {:name => Slate先生,:spouse => Slate夫人}}

如果人没有任何孩子,儿童元素不存在。所以,对于Slate先生,我们可以检查他是否有父母:

  slate_has_children =!slate [:person] [:children ]。零? 

那么,如果我们不知道slate是一个请考虑:

  dino = {:pet => {:name => Dino}} 

我们不能轻易地检查孩子:

  dino_has_children =!dino [:person] [:children] .nil? 
NoMethodError:undefined方法`[]'for nil:NilClass

检查哈希的结构,特别是如果它深入嵌套(甚至比这里提供的示例更深)吗?也许一个更好的问题是:Ruby方式是做什么的?

解决方案

最明显的方法是只需检查每一步的方式:

  has_children = slate [:person]&& slate [:person] [:children] 

使用.nil?真的只有当你使用false作为占位符值,并且在实践中这是很罕见的。

:如果您使用的是Ruby 2.3或更高版本,则有一个内置 dig

如果没有,您还可以定义自己的Hashdig方法,可以大大简化这一点:

  class Hash 
def dig(* path)
path.inject(self)do | location,key |
location.respond_to?(:keys)?位置[key]:nil
end
end
end

这个方法将检查方法的每一步,并避免在调用nil时跳闸。对于浅层结构,实用程序有些限制,但对于深层嵌套的结构,我发现它是非常宝贵的:

  has_children = slate.dig person,:children)

你也可以让这个更强大,例如:条目实际上是填充的:

  children = slate.dig(:person,:children)
has_children = children& & !children.empty?


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"}} 

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?

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

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]

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.

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

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)

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 Style:如何检查是否存在嵌套的哈希元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆