This time I would like to provide another solution: normalized -> store original key value pairs -> grab the original key who has larger value as the key for the difference.
h1 = {"Cat" => 100, "Dog" => 5, "Bird" => 2, "Snake" => 10}
h1.default = 0
h2 = {"cat" => 50, "dog" => 3, "BIRD" => 4, "Mouse" => 75, "Snake" => 10}
h2.default = 0
h3 = {"Cat" => 50, "Dog" => 2, "BIRD" => -2, "Mouse" => -75}
class Hash
def difference(subtrahend)
# create a hash which contains all normalized keys
all_pairs = (self.keys.map{|x| x.downcase} + subtrahend.keys.map{|x| x.downcase}).uniq.inject({}) do |pairs, key|
pairs[key] = []
pairs
end
#=> {"mouse"=>[], "cat"=>[], "snake"=>[], "bird"=>[], "dog"=>[]}
# push original key value pairs into array which is the value of just created hash
[self, subtrahend].each_with_index do |hsh, idx|
hsh.each_pair { |k, v| all_pairs[k.downcase].push([k, v]) }
all_pairs.each_value { |v| v.push([nil, 0]) if v.size == idx }
end
#=> {"mouse"=>[[nil, 0], ["Mouse", 75]], "cat"=>[["Cat", 100], ["cat", 50]], "snake"=>[["Snake", 10], ["Snake", 10]], "bird"=>[["Bird", 2], ["BIRD", 4]], "dog"=>[["Dog", 5], ["dog", 3]]}
results = {}
all_pairs.each_value do |values|
diff = values[0][1] - values[1][1]
# always take the key whose value is larger
if diff > 0
results[values[0][0]] = diff
elsif diff < 0
results[values[1][0]] = diff
end
end
return results
end
end
puts h1.difference(h2).inspect #=> {"Cat" => 50, "Dog" => 2, "BIRD" => -2, "Mouse" => -75}
h1.difference(h2) == h3 ? puts("Pass") : puts("Fail") #=> "Pass"
According to what you described, this one does a pretty good job. The result is exactly what you've shown (key is not normalized in the final result, but depends on whose value is bigger).