Ruby: What is the easiest method to update Hash values?

RubyHash

Ruby Problem Overview


Say:

h = { 1 => 10, 2 => 20, 5 => 70, 8 => 90, 4 => 34 }

I would like to change each value v to foo(v), such that h will be:

h = { 1 => foo(10), 2 => foo(20), 5 => foo(70), 8 => foo(90), 4 => foo(34) }

What is the most elegant way to achieve this ?

Ruby Solutions


Solution 1 - Ruby

You can use update (alias of merge!) to update each value using a block:

hash.update(hash) { |key, value| value * 2 }

Note that we're effectively merging hash with itself. This is needed because Ruby will call the block to resolve the merge for any keys that collide, setting the value with the return value of the block.

Solution 2 - Ruby

Rails (and Ruby 2.4+ natively) have Hash#transform_values, so you can now do {a:1, b:2, c:3}.transform_values{|v| foo(v)}

https://ruby-doc.org/core-2.4.0/Hash.html#method-i-transform_values

If you need it to work in nested hashes as well, Rails now has deep_transform_values(source):

hash = { person: { name: 'Rob', age: '28' } }

hash.deep_transform_values{ |value| value.to_s.upcase }
# => {person: {name: "ROB", age: "28"}}

Solution 3 - Ruby

This will do:

h.each {|k, v| h[k] = foo(v)}

Solution 4 - Ruby

The following is slightly faster than @Dan Cheail's for large hashes, and is slightly more functional-programming style:

new_hash = Hash[old_hash.map {|key, value| key, foo(value)}]

Hash#map creates an array of key value pairs, and Hash.[] converts the array of pairs into a hash.

Solution 5 - Ruby

There's a couple of ways to do it; the most straight-forward way would be to use Hash#each to update a new hash:

new_hash = {}
old_hash.each do |key, value|
  new_hash[key] = foo(value)
end

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMisha MoroshkoView Question on Stackoverflow
Solution 1 - RubyGareveView Answer on Stackoverflow
Solution 2 - RubyMaximusDominusView Answer on Stackoverflow
Solution 3 - RubyrubyprinceView Answer on Stackoverflow
Solution 4 - RubyAndrew GrimmView Answer on Stackoverflow
Solution 5 - RubydnchView Answer on Stackoverflow