Menu
Coddy logo textTech

Iterating Hashes

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

Hashes are enumerable, so you can iterate them just like arrays. There are three common patterns, depending on what you want.

each hands you both the key and value:

prices = { apple: 1, bread: 3, milk: 4 }
prices.each do |item, price|
  puts "#{item}: $#{price}"
end

each_key walks just the keys:

prices.each_key { |k| puts k }   # apple, bread, milk

each_value walks just the values:

prices.each_value { |v| puts v }   # 1, 3, 4

And every Enumerable method you saw last chapter, map, select, reduce: works on hashes too. You just receive a key/value pair (or a 2-element array) per iteration:

prices.select { |item, price| price > 2 }
# {bread: 3, milk: 4}
challenge icon

Challenge

Medium

You're applying a sale to a price list. The hash prices is given (item symbol => price integer).

Read one line of input: a comma-separated list of items to discount by 50% (matching the symbols in the hash, by name).

Print, in this order:

  1. One line per item in the format <item>: <item>: $<final_price>lt;final_price>, where the final price is the discounted value when the item is in the discount list, or the original value otherwise. Iterate with each. Items keep their original order. Use integer division for the discount (price / 2).
  2. Was: Was: $<n>lt;n>: the original total (use values.sum)
  3. Now: Now: $<n>lt;n>: the post-discount total
  4. The names of items whose final price is still above 2, joined with , (use select + keys on the new hash)

For input bread,milk with the default hash, the output is:

apple: $1
bread: $1
milk: $2
cheese: $6
Was: $14
Now: $10
cheese

Cheat sheet

Iterating over hashes with each, each_key, each_value:

prices = { apple: 1, bread: 3, milk: 4 }

prices.each { |item, price| puts "#{item}: $#{price}" }
prices.each_key { |k| puts k }
prices.each_value { |v| puts v }

Enumerable methods like map, select, and reduce also work on hashes, receiving a key/value pair per iteration:

prices.select { |item, price| price > 2 }
# { bread: 3, milk: 4 }

Useful hash methods: .values.sum to sum all values, .keys to get an array of keys.

Try it yourself

prices = { apple: 1, bread: 3, milk: 4, cheese: 6 }
discount = gets.chomp.split(",").map(&:to_sym)

# TODO: build final-price hash via each; print lines, totals, expensive items
quiz iconTest yourself

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

All lessons in Logic & Flow