Ruby - mapping an array to hashmap
RubyHashmapRuby Problem Overview
I have an array, and a function that returns a value given a value. Ultimately I want to create a hashmap that has the values of the array as key value, and the result of f(key_value) as the value. Is there a clean, simple way, like similar to each/map of Array, of doing this using block?
So something that is equivalent to
hsh = {}
[1,2,3,4].each do |x|
hsh[x] = f(x)
end
but looks more similar to this, in that it's simple and one line?
results = array.map { | x | f(x) }
Ruby Solutions
Solution 1 - Ruby
Note that since Ruby 2.1.0 you can also use Array#to_h, like this:
[1,2,3,4].map{ |x| [x, f(x)] }.to_h
Solution 2 - Ruby
Ruby 2.6.0 enables passing a block to the to_h
-method. This enables an even shorter syntax for creating a hash from an array:
[1, 2, 3, 4].to_h { |x| [x, f(x)] }
Solution 3 - Ruby
You could also define the function as the hash's default value:
hash = Hash.new {|hash, key| hash[key] = f(key) }
Then when you lookup a value, the hash will calculate and store it on the fly.
hash[10]
hash.inspect #=> { 10 => whatever_the_result_is }
Solution 4 - Ruby
You need each_with_object
.
def f x
x * 2
end
t = [1, 2, 3, 4].each_with_object({}) do |x, memo|
memo[x] = f(x)
end
t # => {1=>2, 2=>4, 3=>6, 4=>8}
Another one:
t2 = [1, 2, 3, 4].map{|x| [x, f(x)]}
Hash[t2] # => {1=>2, 2=>4, 3=>6, 4=>8}
Solution 5 - Ruby
Check out the Hash::[] method.
Hash[ [1,2,3,4].collect { |x| [x, f(x)] } ]
Solution 6 - Ruby
Using Facets' mash (method to convert enumerable to hashes):
[1, 2, 3, 4].mash { |x| [x, f(x)] }
From Ruby 2.1:
[1, 2, 3, 4].map { |x| [x, f(x)] }.to_h
Solution 7 - Ruby
You're looking for reduce()|inject()
method:
elem = [1,2,3,4]
h = elem.reduce({}) do |res, x|
res[x] = x**2
res
end
puts h
The argument passed to reduce({})
is the initial value of an intermediate object that is passed to the block as res
variable. In each iteration we're adding new pair key: value
to the res
Hash and returing the Hash to be used in next iteration.
The method above precomputes a very practical hash of squared values:
{1=>1, 2=>4, 3=>9, 4=>16}