简体   繁体   中英

Ruby: Mapping a Hash

In Python, I can create a test hash with list comprehension that I check against a suite of test(s). How can I achieve the same thing in ruby? (I'm running on ruby 1.9.3)

Python:

test = {x: self.investor.annual_return(x) for x in xrange(1, 6)}

Ruby (attempt):

test = Hash[(1..5).map { |x| [x, @investor.annual_return(x)] }]

You want something like:

test = {}
(1..5).map { |i| test[i] = @investor.annual_return(i) }

I think your Ruby code is fine, depending on what version of Ruby you're running.

Starting with:

class Investor
  def annual_return(i)
    i * i
  end
end

investor = Investor.new

In Ruby 1.9+, this will work:

test = Hash[ (1..5).map { |x| [x, investor.annual_return(x)] } ]
test # => {1=>1, 2=>4, 3=>9, 4=>16, 5=>25}

However, prior to 1.9, Hash wouldn't convert an array of arrays containing key/value pairs, so we had to get a bit fancier, and flatten the nested elements into a single array, then "explode" those elements for Hash:

test = Hash[ *(1..5).map { |x| [x, investor.annual_return(x)] }.flatten ]
test # => {1=>1, 2=>4, 3=>9, 4=>16, 5=>25}

The result is the same, it's just less hassle these days.

And, just to show what Ruby does as we build a hash this way:

(1..5).map { |x| [x, investor.annual_return(x)] }
# => [[1, 1], [2, 4], [3, 9], [4, 16], [5, 25]]

(1..5).map { |x| [x, investor.annual_return(x)] }.flatten
# => [1, 1, 2, 4, 3, 9, 4, 16, 5, 25]

You often see:

test = (1..5).reduce({}) {|h, x| h[x] = @investor.annual_return(x); h}

but (since Ruby 1.9) many prefer Enumerable#each_with_object :

test = (1..5).each_with_object({}) {|x, h| h[x] = @investor.annual_return(x)}

in part because there is no need to return the object h to the iterator, as there is with Enumerable#reduce (aka inject ).

如果我正确理解您要执行的操作,则可以尝试以下操作:

{}.tap { |x| (1..5).each do |y| x[y] = @investor.annual_return(i) end }

You can do it easily with:

(1..5).map { |x| [x, @investor.annual_return(x)] }.to_h

(Doc: Array#to_h )

Hash[*array] is used to construct a hash from a flat array ( [key1, value1, key2, value2, keyN, valueN] ), whereas Array#to_h is used to construct a hash from an array of key-value pairs ( [ [key1, value1], [key2, value2], [keyN, valueN] ] ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM