Menu
Coddy logo textTech

Merging and Transforming

Part of the Logic & Flow section of Coddy's Ruby journey — lesson 36 of 56.

Two operations come up so often when working with hashes that Ruby gives them their own methods.

merge combines two hashes into a new one. When both have the same key, the right-hand value wins:

defaults = { color: "red", size: "M" }
custom   = { size: "L" }
settings = defaults.merge(custom)
puts settings.inspect   # {color: "red", size: "L"}

Neither original is modified, merge returns a new hash.

transform_values builds a new hash with the same keys but each value passed through a block:

prices = { apple: 1, bread: 3 }
with_tax = prices.transform_values { |p| p * 1.2 }
puts with_tax.inspect   # {apple: 1.2, bread: 3.6}

And transform_keys does the same for keys, useful when converting strings to symbols, or normalizing case:

{ "a" => 1, "B" => 2 }.transform_keys(&:upcase)
# {"A"=>1, "B"=>2}
challenge icon

Challenge

Medium

Two cart hashes are given: monday and tuesday, each maps a string item name to an integer quantity. The shop wants a normalized two-day total.

Produce one final hash by:

  1. merge-ing the two hashes with a block so that keys present in both have their quantities summed (not overwritten)
  2. transform_keys(&:to_sym) on the result, so keys become symbols
  3. transform_values to apply a 10% bulk discount: every quantity becomes (qty * 9 / 10) using integer math

Print the final hash with inspect.

For the default data, the output is:

{:apples=>9, :bread=>4, :milk=>5, :cheese=>1}

(Apples: 5 + 5 = 10, then 9. Bread: 3 + 2 = 5, then 4. Milk: 6 only on Monday → 5. Cheese: 2 only on Tuesday → 1.)

Cheat sheet

merge combines two hashes; when keys conflict, the right-hand value wins:

defaults = { color: "red", size: "M" }
custom   = { size: "L" }
settings = defaults.merge(custom)
# {color: "red", size: "L"}

Pass a block to merge to handle duplicate keys manually:

a.merge(b) { |key, old_val, new_val| old_val + new_val }

transform_values returns a new hash with each value passed through a block:

prices = { apple: 1, bread: 3 }
prices.transform_values { |p| p * 1.2 }
# {apple: 1.2, bread: 3.6}

transform_keys does the same for keys:

{ "a" => 1 }.transform_keys(&:upcase)  # {"A"=>1}
{ "a" => 1 }.transform_keys(&:to_sym)  # {a: 1}

Try it yourself

monday  = { "apples" => 5, "bread" => 3, "milk" => 6 }
tuesday = { "apples" => 5, "bread" => 2, "cheese" => 2 }

# TODO: merge-with-block to sum overlapping keys, then symbolize keys,
#       then apply * 9 / 10 to every value, then inspect
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Logic & Flow