Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

arrays

ruby

hash

I have a simple array:

arr = ["apples", "bananas", "coconuts", "watermelons"] 

I also have a function f that will perform an operation on a single string input and return a value. This operation is very expensive, so I would like to memoize the results in the hash.

I know I can make the desired hash with something like this:

h = {} arr.each { |a| h[a] = f(a) } 

What I'd like to do is not have to initialize h, so that I can just write something like this:

h = arr.(???) { |a| a => f(a) } 

Can that be done?

like image 699
Wizzlewott Avatar asked May 31 '10 12:05

Wizzlewott


People also ask

How do you turn an array into a Hash in Ruby?

The to_h method is defined in the array class. It works to convert an array to a hash in the form of key-value pairs. The method converts each nested array into key-value pairs. The method also accepts a block.

How do you create a Hash in Ruby?

In Ruby you can create a Hash by assigning a key to a value with => , separate these key/value pairs with commas, and enclose the whole thing with curly braces.

How do you push values into an array of Hash in Ruby?

You are allowed to create an array of hashes either by simply initializing array with hashes or by using array. push() to push hashes inside the array. Note: Both “Key” and :Key acts as a key in a hash in ruby.

How do you pop an array element in Ruby?

The pop() function in Ruby is used to pop or remove the last element of the given array and returns the removed elements. Parameters: Elements : This is the number of elements which are to be removed from the end of the given array.


2 Answers

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

def f(fruit)    fruit + "!" end  arr = ["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)] }] 
like image 136
microspino Avatar answered Sep 18 '22 06:09

microspino


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.

like image 30
dmastylo Avatar answered Sep 18 '22 06:09

dmastylo