目前我正在做以下事情,但我相信一定有更好的方法:
def birthday_defined?(map)
map && map[:extra] && map[:extra][:raw_info] && map[:extra][:raw_info][:birthday]
end
可能存在仅map[:extra]
定义的情况,然后如果我不使用上面检查的代码,我最终会得到 Nil 异常错误原因map[:extra][:raw_info]
不存在。
我有两种方法。两者都有相同的代码,但略有不同:
# Method 1
def birthday_defined?(map)
map[:extra][:raw_info][:birthday] rescue nil # rescues current line
end
# Method 2
def birthday_defined?(map)
map[:extra][:raw_info][:birthday]
rescue # rescues whole method
nil
end
如果您使用的是 Rails,那么您可以使用try
(and NilClass#try
):
value = map.try(:[], :extra).try(:[], :raw_info).try(:[], :birthday)
这看起来有点重复:它只是一遍又一遍地做同样的事情,同时将一个步骤的结果提供给下一步。该代码模式意味着我们有一个隐藏的注入:
value = [:extra, :raw_info, :birthday].inject(map) { |h, k| h.try(:[], k) }
这种方法很好地推广到map
您想到的任何路径:
path = [ :some, :path, :of, :keys, :we, :care, :about ]
value = path.inject(map) { |h, k| h.try(:[], k) }
然后你可以看看value.nil?
。
当然,如果你不使用 Rails,那么你需要一个替代品,try
但这并不难。
使用开始/救援块。
begin
map[:extra][:raw_info][:birthday]
rescue Exception => e
'No birthday! =('
end
这是惯用的为什么要这样做。是的,它可能有点麻烦。
如果你想扩展Hash
一点,你可以做一些很酷的东西,比如关键路径。请参阅使用点分路径键字符串访问 Ruby 哈希
def birthday_defined?
map.dig('extra.raw_info.birthday')
end
这有点hacky,但它会起作用:
def birthday_defined?(map)
map.to_s[":birthday"]
end
如果map
包含:birthday
,那么它将返回将true
在条件语句中评估为的字符串,而如果它不包含:birthday
,它将返回nil
。
注意:这假设密钥:birthday
不会出现在map
.
这应该适合你:
def birthday_defined?(map)
map
.tap{|x| (x[:extra] if x)
.tap{|x| (x[:raw_info] if x)
.tap{|x| (x[:birthday] if x)
.tap{|x| return x}}}}
end