是否可以修改hash
类,以便给定两个哈希值,可以创建一个只包含一个哈希中但不包含另一个哈希值的新哈希值?
E.g:
h1 = {"Cat" => 100, "Dog" => 5, "Bird" => 2, "Snake" => 10}
h2 = {"Cat" => 100, "Dog" => 5, "Bison" => 30}
h1.difference(h2) = {"Bird" => 2, "Snake" => 10}
可选地,difference
方法可以包括任何键/值对,使得键存在于两个哈希中,但它们之间的值不同。
答案 0 :(得分:12)
h1 = {"Cat" => 100, "Dog" => 5, "Bird" => 2, "Snake" => 10}
h2 = {"Cat" => 999, "Dog" => 5, "Bison" => 30}
案例1:将所有键/值对k=>v
保留在h1
k
这是一种方式:
h1.dup.delete_if { |k,_| h2.key?(k) }
#=> {"Bird"=>2, "Snake"=>10}
这是另一个:
class Array
alias :spaceship :<=>
def <=>(o)
first <=> o.first
end
end
(h1.to_a - h2.to_a).to_h
#=> {"Bird"=>2, "Snake"=>10}
class Array
alias :<=> :spaceship
remove_method(:spaceship)
end
案例2:保留h1
中不在h2
您需要的只是:
(h1.to_a - h2.to_a).to_h
#=> {"Cat"=>100, "Bird"=>2, "Snake"=>10}
Ruby 2.0中引入了Array#to_h。对于早期版本,请使用Hash[]。
答案 1 :(得分:6)
使用reject
方法:
class Hash
def difference(other)
reject do |k,v|
other.has_key? k
end
end
end
如果值相同,则仅拒绝键/值对(根据mallanaga的建议,通过对原始答案的评论,我已将其删除):
class Hash
def difference(other)
reject do |k,v|
other.has_key?(k) && other[k] == v
end
end
end
答案 2 :(得分:2)
你可以这样做:
h2.each_with_object(h1.dup){|(k, v), h| h.delete(k)}
答案 3 :(得分:0)
尝试使用hashdiff gem。
diff=HashDiff.diff(h1,h2)
答案 4 :(得分:0)
对于深层嵌套,您可以添加一些递归,例如(未嵌套)
class Hash
def -(h2)
raise ArgumentError unless h2.is_a?(Hash)
h1 = dup
h1.delete_if do |k, v|
if v.is_a?(Hash) && h2[k].is_a?(Hash)
h1[k] = v - h2[k]
h1[k].blank?
else
h2[k] == v
end
end
end
end
end