是否定义了嵌套哈希?()

确定@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否则返回与:key2true关联的值。

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 

你会得到这个值,如果它不存在则为零。