In Ruby, how do I make a hash from an array? In Ruby, how do I make a hash from an array? arrays arrays

In Ruby, how do I make a hash from an array?


Say you have a function with a funtastic name: "f"

def f(fruit)   fruit + "!"endarr = ["apples", "bananas", "coconuts", "watermelons"]h = Hash[ *arr.collect { |v| [ v, f(v) ] }.flatten ]

will give you:

{"watermelons"=>"watermelons!", "bananas"=>"bananas!", "apples"=>"apples!", "coconuts"=>"coconuts!"}

Updated:

As mentioned in the comments, Ruby 1.8.7 introduces a nicer syntax for this:

h = Hash[arr.collect { |v| [v, f(v)] }]


Did some quick, dirty benchmarks on some of the given answers. (These findings may not be exactly identical with yours based on Ruby version, weird caching, etc. but the general results will be similar.)

arr is a collection of ActiveRecord objects.

Benchmark.measure {    100000.times {        Hash[arr.map{ |a| [a.id, a] }]    }}

Benchmark @real=0.860651, @cstime=0.0, @cutime=0.0, @stime=0.0, @utime=0.8500000000000005, @total=0.8500000000000005

Benchmark.measure {     100000.times {        h = Hash[arr.collect { |v| [v.id, v] }]    }}

Benchmark @real=0.74612, @cstime=0.0, @cutime=0.0, @stime=0.010000000000000009, @utime=0.740000000000002, @total=0.750000000000002

Benchmark.measure {    100000.times {        hash = {}        arr.each { |a| hash[a.id] = a }    }}

Benchmark @real=0.627355, @cstime=0.0, @cutime=0.0, @stime=0.010000000000000009, @utime=0.6199999999999974, @total=0.6299999999999975

Benchmark.measure {    100000.times {        arr.each_with_object({}) { |v, h| h[v.id] = v }    }}

Benchmark @real=1.650568, @cstime=0.0, @cutime=0.0, @stime=0.12999999999999998, @utime=1.51, @total=1.64

In conclusion

Just because Ruby is expressive and dynamic, doesn't mean you should always go for the prettiest solution. The basic each loop was the fastest in creating a hash.


h = arr.each_with_object({}) { |v,h| h[v] = f(v) }