与另一个嵌套哈希相比,从嵌套哈希中查找丢失的密钥

时间:2014-07-22 14:13:33

标签: ruby-on-rails ruby-on-rails-4 hash

我有两个嵌套的哈希值(hash1,hash2),偶然碰巧是从yml文件生成的哈希值。我需要找到hash1中存在但不在hash2中的所有键(完整的父链)。

鉴于这两个哈希值,输出应为hash_diff。

hash1 = {"A" => 1, "B" => {"C" => 2, "D" => 3} , "E" => 1} 
hash2 = {"A" => 1, "B" => {"C" => 2} }
hash_diff = {"B" => {"D" => 3}, "E" => 1} 

请注意,我想要一个类似哈希差异的东西,它只考虑密钥,而不是值。

3 个答案:

答案 0 :(得分:1)

这是解决方案。虽然我修改了原来的hash1 所以用法是:

hash_diff(hash1,hash2)
hash_diff_var = hash1

def self.hash_diff_helper(hash1,hash2)
    hash1.each_pair do |k,v|
      if v.is_a?(Hash) && hash2.key?(k)
        hash_diff_helper(v,hash2[k])
      elsif !v.is_a?(Hash) && hash2.key?(k)
        hash1.delete(k)
      end
    end
  end

  def self.hash_diff(hash1,hash2)
    hash_diff_helper(hash1,hash2)
    hash1.select!{|k,v| v.present?}
  end

答案 1 :(得分:0)

我想修补Hash以获得你想要的函数,所以本质上是一个在hash2中不存在时返回nil的合并,然后在hash上实现compact:

class ::Hash
     def deep_nil_merge(second)
        merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : nil }
        self.merge(second, &merger)
     end

  def compact
    delete_if{|k, v|

      (v.is_a?(Hash) and v.respond_to?('empty?') and v.compact.empty?) or
          (v.nil?)  or
          (v.is_a?(String) and v.empty?)
    }
  end


end

然后运行

hash1.deep_nil_merge(hash2).compact

答案 2 :(得分:0)

有一些宝石可以帮助你实现这一目标。

如果你只想要一个纯粹的差异https://github.com/Blargel/easy_diff是个不错的选择。它为您提供了已添加和删除的内容,以便发挥作用。

更健壮的选项是https://github.com/liufengyun/hashdiff,它不会修改Hash对象,但会以点表示法返回所有差异的数组。