4

目前我正在做以下事情,但我相信一定有更好的方法:

def birthday_defined?(map)
    map && map[:extra] && map[:extra][:raw_info] && map[:extra][:raw_info][:birthday]
end

可能存在仅map[:extra]定义的情况,然后如果我不使用上面检查的代码,我最终会得到 Nil 异常错误原因map[:extra][:raw_info]不存在。

4

6 回答 6

1

我有两种方法。两者都有相同的代码,但略有不同:

# 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
于 2012-10-22T17:17:26.690 回答
1

如果您使用的是 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但这并不难。

于 2012-10-22T17:40:17.263 回答
0

使用开始/救援块。

begin
  map[:extra][:raw_info][:birthday]
rescue Exception => e
  'No birthday! =('
end
于 2012-10-22T17:12:59.607 回答
0

这是惯用的为什么要这样做。是的,它可能有点麻烦。

如果你想扩展Hash一点,你可以做一些很酷的东西,比如关键路径。请参阅使用点分路径键字符串访问 Ruby 哈希

def birthday_defined?
  map.dig('extra.raw_info.birthday')
end
于 2012-10-22T17:13:07.890 回答
0

这有点hacky,但它会起作用:

def birthday_defined?(map)
    map.to_s[":birthday"]
end

如果map包含:birthday,那么它将返回将true在条件语句中评估为的字符串,而如果它不包含:birthday,它将返回nil

注意:这假设密钥:birthday不会出现在map.

于 2012-10-22T18:29:14.000 回答
0

这应该适合你:

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
于 2012-10-22T20:18:26.317 回答