Our Daily Method #11: Hash#inv_multi
Geplaatst door Michiel de Mare di, 19 feb 2008 08:00:00 GMT
Hash
has an invert
-method, but it often happens that you’re dealing with a hash with arrays as values. Naturally, you don’t want arrays as keys – you want every element in the array to turn into a key, with an array of all original keys with that element as the value.
Simple example
{1 => [3,4]}.inv_multi
# => {3=>[1], 4=>[1]}
Complex example
{1 => [3,4,5,6], 2 => [3,4], 4 => 11}.inv_multi
# => {5=>[1], 11=>[4], 6=>[1], 3=>[1, 2], 4=>[1, 2]}
The method itself:
class Hash
def inv_multi
# there's inject! again. daily method #5
inject!({}) do |h,(k,v)| # Is this obvious? If not, say so!
# this lambda binds h and k.
l = lambda {|x| (h[x] ||= []) << k}
if Array === v
v.each(&l)
else # value doesn't have to be an array
l[v]
end
end
end
end