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}"
endeach_key walks just the keys:
prices.each_key { |k| puts k } # apple, bread, milkeach_value walks just the values:
prices.each_value { |v| puts v } # 1, 3, 4And 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
MediumYou'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:
- 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 witheach. Items keep their original order. Use integer division for the discount (price / 2). Was: Was: $<n>lt;n>: the original total (usevalues.sum)Now: Now: $<n>lt;n>: the post-discount total- The names of items whose final price is still above
2, joined with,(useselect+keyson 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
cheeseCheat 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
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Logic & Flow
1Strings In Depth
String Methods OverviewString InterpolationIterating Over StringsSplit and JoinRecap - String Weaver4Blocks, Procs & Lambdas
What is a Block?do..end vs BracesThe yield KeywordBlock ParametersProcs and LambdasRecap - Custom Iterator7Hashes Part 2
Hash.new with DefaultsIterating HashesNested HashesMerging and TransformingRecap - Frequency Counter10Project - Student Records
Project OverviewAdd Student5Enumerable Powerhouse
Select and RejectChaining MapReduce / Injectcount, all?, any?, none?group_by and partitionsort_by, min_by, max_byRecap - Data Pipeline8Advanced Decision Making
Case with Classes & RegexMulti-value whenTernary OperatorInline if / unlessRecap - Grade Classifier