Ruby Language Hashes Modifying keys and values

30% OFF - 9th Anniversary discount on Entity Framework Extensions until December 15 with code: ZZZANNIVERSARY9


You can create a new hash with the keys or values modified, indeed you can also add or delete keys, using inject (AKA, reduce). For example to produce a hash with stringified keys and upper case values:

fruit = { name: 'apple', color: 'green', shape: 'round' }
# => {:name=>"apple", :color=>"green", :shape=>"round"}

new_fruit = fruit.inject({}) { |memo, (k,v)| memo[k.to_s] = v.upcase; memo }

# => new_fruit is {"name"=>"APPLE", "color"=>"GREEN", "shape"=>"ROUND"}

Hash is an enumerable, in essence a collection of key/value pairs. Therefore is has methods such as each, map and inject.

For every key/value pair in the hash the given block is evaluated, the value of memo on the first run is the seed value passed to inject, in our case an empty hash, {}. The value of memo for subsequent evaluations is the returned value of the previous blocks evaluation, this is why we modify memo by setting a key with a value and then return memo at the end. The return value of the final blocks evaluation is the return value of inject, in our case memo.

To avoid the having to provide the final value, you could use each_with_object instead:

new_fruit = fruit.each_with_object({}) { |(k,v), memo| memo[k.to_s] = v.upcase }

Or even map:

new_fruit = Hash[{ |k,v| [k.to_s, v.upcase] }]

(See this answer for more details, including how to manipulate hashes in place.)

Got any Ruby Language Question?