This blog is part of our Ruby 2.4 series.
It is a common use case to transform the values of a hash.
1 2{ a: 1, b: 2, c: 3 } => { a: 2, b: 4, c: 6 } 3 4{ a: "B", c: "D", e: "F" } => { a: "b", c: "d", e: "f" } 5
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.
1 2# Ruby 2.3 Non-destructive version 3 4> hash = { a: 1, b: 2, c: 3 } 5 #=> {:a=>1, :b=>2, :c=>3} 6 7> hash.inject({}) { |h, (k, v)| h[k] = v * 2; h } 8 #=> {:a=>2, :b=>4, :c=>6} 9 10> hash 11 #=> {:a=>1, :b=>2, :c=>3} 12 13> hash = { a: "B", c: "D", e: "F" } 14 #=> {:a=>"B", :c=>"D", :e=>"F"} 15 16> hash.inject({}) { |h, (k, v)| h[k] = v.downcase; h } 17 #=> {:a=>"b", :c=>"d", :e=>"f"} 18 19> hash 20 #=> {:a=>"B", :c=>"D", :e=>"F"} 21
1 2# Ruby 2.3 Destructive version 3 4> hash = { a: 1, b: 2, c: 3 } 5 #=> {:a=>1, :b=>2, :c=>3} 6 7> hash.each { |k, v| hash[k] = v * 2 } 8 #=> {:a=>2, :b=>4, :c=>6} 9 10> hash 11 #=> {:a=>2, :b=>4, :c=>6} 12 13> hash = { a: "B", c: "D", e: "F" } 14 #=> {:a=>"B", :c=>"D", :e=>"F"} 15 16> hash.each { |k, v| hash[k] = v.downcase } 17 #=> {:a=>"b", :c=>"d", :e=>"f"} 18 19> hash 20 #=> {:a=>"b", :c=>"d", :e=>"f"} 21
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.
1 2# Ruby 2.4 Non-destructive version 3 4> hash = { a: 1, b: 2, c: 3 } 5 #=> {:a=>1, :b=>2, :c=>3} 6 7> hash.transform_values { |v| v * 2 } 8 #=> {:a=>2, :b=>4, :c=>6} 9 10> hash 11 #=> {:a=>1, :b=>2, :c=>3} 12 13> hash = { a: "B", c: "D", e: "F" } 14 #=> {:a=>"B", :c=>"D", :e=>"F"} 15 16> hash.transform_values(&:downcase) 17 #=> {:a=>"b", :c=>"d", :e=>"f"} 18 19> hash 20 #=> {:a=>"B", :c=>"D", :e=>"F"} 21
1 2# Ruby 2.4 Destructive version 3 4> hash = { a: 1, b: 2, c: 3 } 5 #=> {:a=>1, :b=>2, :c=>3} 6 7> hash.transform_values! { |v| v * 2 } 8 #=> {:a=>2, :b=>4, :c=>6} 9 10> hash 11 #=> {:a=>2, :b=>4, :c=>6} 12 13> hash = { a: "B", c: "D", e: "F" } 14 #=> {:a=>"B", :c=>"D", :e=>"F"} 15 16> hash.transform_values!(&:downcase) 17 #=> {:a=>"b", :c=>"d", :e=>"f"} 18 19> hash 20 #=> {:a=>"b", :c=>"d", :e=>"f"} 21