是否定义了嵌套哈希?()
确定@hash[:key1][:key2]
是否最简洁的方法是什么,如果@hash
或@hash[:key1]
为零,则不会抛出错误?
如果@hash[:key1]
存在,则( defined?(@hash[:key1][:key2])
返回True(它不确定:key2
是否定义了:key2
)
使用ActiveSupport(Rails)或Backports时,您可以使用try
:
@hash[:key1].try(:fetch, :key2)
你甚至可以处理@hash
nil
:
@hash.try(:fetch, :key1).try(:fetch, :key2)
如果您希望@hash
始终返回缺少键的哈希值:
@hash = Hash.new { |h,k| h[k] = {} } @hash[:foo] # => {}
您还可以定义此递归:
def recursive_hash Hash.new { |h,k| h[k] = recursive_hash } end @hash = recursive_hash @hash[:foo][:bar][:blah] = 10 @hash # => {:foo => {:bar => {:blah => 10}}}
但要回答你的问题:
module HasNestedKey Hash.send(:include, self) def has_nested_key?(*args) return false unless sub = self[args.shift] return true if args.empty? sub.respond_to?(:has_nested_key?) and sub.has_nested_key?(*args) end end @hash.has_nested_key? :key1, :key2
也许我错过了一些东西,但如果你关心的只是简洁……为什么不呢:
@hash && @hash[:key1] && @hash[:key1][:key2]
或者如果你想保存几个字符
@hash && (h = @hash[:key1]) && h[:key2]
如果其中任何部分失败,则返回nil
否则返回与:key2
或true
关联的值。
defined?
的原因是defined?
即使出现:key2
情况也返回true :key2
不存在,因为它只检查您引用的对象是否存在,在这种情况下是方法[]
,它是方法fetch
的别名,它存在于哈希@hash[:key1]
但是如果返回nil,则nil上没有fetch方法,它将返回nil
。 话虽这么说,如果你不得不深入嵌入哈希,在某些时候调用会更有效:
defined?(@hash[:key1][:key2][:key3]) && @hash[:key1][:key2][:key3]
使用Hash #fetch
你可以使用Hash #fetch方法,默认值为{}
,这样可以安全地调用has_key?
即使第一级密钥不存在。 例如
!hash.nil? && hash.fetch(key1, {}).has_key?(key2)
替代
或者,您可以使用条件运算符,例如
!hash.nil? && (hash.has_key?(key1) ? hash[key1].has_key?(key2) : false)
即如果hash
没有密钥key1
返回false
而不查找第二级密钥。 如果它确实有key1
则返回检查key1's
key2
值的结果。
另外,如果你想检查hash[key1]'s
值是否有has_key?
调用之前的方法:
!hash.nil? && (hash.has_key?(key1) ? hash[key1].respond_to?(:has_key?) && hash[key1].has_key?(key2) : false)
@hash[:key1].has_key? :key2
如果你不关心从@hash[:key1][:key2] == nil
区分不存在的@hash[:key1][:key2]
(在3个级别中的任何一个级别),这是非常干净的,适用于任何深度:
[:key1,:key2].inject(hash){|h,k| h && h[k]}
如果您希望将nil
视为现有,请改用:
(hash[:key1].has_key?(:key2) rescue false)
我刚刚发现的另一个选择是使用seek
方法扩展Hash。 技术来自Corey O’Daniel 。
将其粘贴在初始化程序中:
class Hash def seek(*_keys_) last_level = self sought_value = nil _keys_.each_with_index do |_key_, _idx_| if last_level.is_a?(Hash) && last_level.has_key?(_key_) if _idx_ + 1 == _keys_.length sought_value = last_level[_key_] else last_level = last_level[_key_] end else break end end sought_value end end
然后打电话:
@key_i_need = @hash.seek :one, :two, :three
你会得到这个值,如果它不存在则为零。