This blog is part of our Ruby 2.4 series.

It is a common use case to transform the values of a hash.

{ a: 1 , b: 2 , c: 3 } => { a: 2 , b: 4 , c: 6 } { a: "B" , c: "D" , e: "F" } => { a: "b" , c: "d" , e: "f" }

We can transform the values of a hash destructively (i.e. modify the original hash with new values) or non-destructively (i.e. return a new hash instead of modifying the original hash).

Prior to Ruby 2.4, we need to use following code to transform the values of a hash.

# Ruby 2.3 Non-destructive version > hash = { a: 1 , b: 2 , c: 3 } #=> {:a=>1, :b=>2, :c=>3} > hash . inject ({}) { | h , ( k , v ) | h [ k ] = v * 2 ; h } #=> {:a=>2, :b=>4, :c=>6} > hash #=> {:a=>1, :b=>2, :c=>3} > hash = { a: "B" , c: "D" , e: "F" } #=> {:a=>"B", :c=>"D", :e=>"F"} > hash . inject ({}) { | h , ( k , v ) | h [ k ] = v . downcase ; h } #=> {:a=>"b", :c=>"d", :e=>"f"} > hash #=> {:a=>"B", :c=>"D", :e=>"F"}

# Ruby 2.3 Destructive version > hash = { a: 1 , b: 2 , c: 3 } #=> {:a=>1, :b=>2, :c=>3} > hash . each { | k , v | hash [ k ] = v * 2 } #=> {:a=>2, :b=>4, :c=>6} > hash #=> {:a=>2, :b=>4, :c=>6} > hash = { a: "B" , c: "D" , e: "F" } #=> {:a=>"B", :c=>"D", :e=>"F"} > hash . each { | k , v | hash [ k ] = v . downcase } #=> {:a=>"b", :c=>"d", :e=>"f"} > hash #=> {:a=>"b", :c=>"d", :e=>"f"}

transform_values and transform_values! from Active Support

Active Support has already implemented handy methods Hash#transform_values and Hash#transform_values! to transform hash values.

Now, Ruby 2.4 has also implemented Hash#map_v and Hash#map_v! and then renamed to Hash#transform_values and Hash#transform_values! for the same purpose.

# Ruby 2.4 Non-destructive version > hash = { a: 1 , b: 2 , c: 3 } #=> {:a=>1, :b=>2, :c=>3} > hash . transform_values { | v | v * 2 } #=> {:a=>2, :b=>4, :c=>6} > hash #=> {:a=>1, :b=>2, :c=>3} > hash = { a: "B" , c: "D" , e: "F" } #=> {:a=>"B", :c=>"D", :e=>"F"} > hash . transform_values ( & :downcase ) #=> {:a=>"b", :c=>"d", :e=>"f"} > hash #=> {:a=>"B", :c=>"D", :e=>"F"}