We all know and love the map method in Ruby (and other functional-ish languages). Given some list of objects, we get back an equal-sized array of potentially different objects. In Ruby we can map against arrays, hashes, sets, etc.; basically, anything that is Enumerable.
From time-to-time, though, I need to convert some list of object into a hash. Ergo, I need to map-to-hash or mash.
For instance, let’s say I want to map an array of User records to a hash with email addresses pointing to the User records? Without much thought I could write it this way:
users = User.find(:all) # Not smart :)
hashed_users = users.inject({}) do |acc,u|
acc[u.email] = u
acc
end
I would rather do the following:
users = User.find(:all) # Still not smart :)
hashed_users = users.mash {|u| {u.email => u} }
It’s not a HUGE change, but it does let me say what I want to say without all the accumulator cruft.
Implementation
Simple, straight forward, and usable by anything that is Enumerable.
module Enumerable
def mash
self.inject({}) { |a,i| a.merge( yield(i) ) }
end
end
Acknowledgements
After writing my mash, I realized others have probably done this many times before and a quick search found the below posts (Ruby specific). I was actually wrong about my assumption. I only found one post. Of course, I didn’t search very hard and other languages probably do the same.
- Map array to hash - There are actually one too many loops in vinterbleg’s implementation. And it’s Array specific where it should be Enumerable generic.