我有两个嵌套的哈希值(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}
请注意,我想要一个类似哈希差异的东西,它只考虑密钥,而不是值。
答案 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对象,但会以点表示法返回所有差异的数组。