Remapping the Keys and Values of a Hash
Problem
You have two hashes with common keys but differing values. You want to create a new hash that maps the values of one hash to the values of another.
Solution
class Hash def tied_with(hash) remap do |h,key,value| h[hash[key]] = value end.delete_if { |key,value| key.nil? || value.nil? } end
Here is the Hash#remap method:
def remap(hash={}) each { |k,v| yield hash, k, v } hash end end
Here's how to use Hash#tied_with to merge two hashes:
a = {1 => 2, 3 => 4} b = {1 => 'foo', 3 => 'bar'} a.tied_with(b) # => {"foo"=>2, "bar"=>4} b.tied_with(a) # => {2=>"foo", 4=>"bar"}
Discussion
This remap method can be handy when you want to make a similar change to every item in a hash. It is also a good example of using the yield method.
Hash#remap is conceptually similar to Hash#collect, but Hash#collect builds up a nested array of key-value pairs, not a new hash.
See Also
- The Facets library defines methods Hash#update_each and Hash#replace_each! for remapping the keys and values of a hash