将数组映射为散列表

我有一个数组和一个函数,它返回一个给定值的值。最终,我想创建一个散列表,它将数组的值作为键值,将 f (key _ value)的结果作为值。有没有一种干净、简单的方法,类似于 Array 的每个/map,使用块来完成这项工作?

所以等价于

hsh = {}
[1,2,3,4].each do |x|
hsh[x] = f(x)
end

但看起来更像这个,因为它很简单,只有一行?

results = array.map { | x | f(x) }
88779 次浏览

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}

Check out the Hash::[] method.

Hash[ [1,2,3,4].collect { |x| [x, f(x)] } ]

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 }

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

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

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}

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)] }

Also, index_with would be helpful:

a = ['a', 'bsdf', 'wqqwc']
a.index_with(&:size)
=> {"a"=>1, "bsdf"=>4, "wqqwc"=>5}