Hashes
Ruby is a dynamic, beginner-friendly programming language, and a Hash stores data as key-value pairs so you can look things up by a meaningful name instead of a position.
Learn Hashes in our free Ruby course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick reference.
Part of the free Ruby course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
By the end of this lesson you'll create hashes, read and update values by key, iterate over pairs, and use defaults for missing keys.
What You'll Learn in This Lesson
1️⃣ Creating, Reading, and Updating
Write a hash with {' '} . Symbol keys (the name: form) are the norm. Read with hash[:key] , and add or change a value by assigning to a key. An unknown key returns nil rather than erroring.
2️⃣ Iterating and Defaults
Loop over pairs with each and two block parameters. Use fetch when you want a missing key to raise (or supply a default). And Hash.new(0) gives every missing key a starting value — the classic recipe for counting things.
Your turn. Manage a small shop inventory hash. Fill in the TODO lines, then run it.
Count how many times each word appears in a sentence using Hash.new(0) . Run with ruby wordcount.rb .
📋 Quick Reference — Hashes
Practice quiz
What does a Hash store?
- An ordered list indexed by number
- Only strings
- Key-value pairs looked up by key
- A single value
Answer: Key-value pairs looked up by key. A Hash maps keys to values, so you retrieve data by a meaningful key rather than a position.
Given , what does return?
- nil
- An error
- false
- ""
Answer: nil. By default, looking up an unknown key returns nil rather than raising.
What does return?
- {:a=>1, :b=>3}
- {:a=>1}
- {:a=>2}
- {:a=>2, :b=>3}
Answer: {:a=>2, :b=>3}. merge overrides existing keys with the argument's values: a becomes 2 and b is added.
What does give you?
- A frozen hash
- A default value of 0 for missing keys
- An array of zeros
- A KeyError on miss
Answer: A default value of 0 for missing keys. Hash.new(0) returns 0 for any missing key — perfect for counters with .
How does differ from for a missing key?
- fetch raises KeyError (or returns a default you pass)
- No difference
- fetch returns nil
- fetch is slower only
Answer: fetch raises KeyError (or returns a default you pass). hash[:missing] returns nil, but hash.fetch(:missing) raises KeyError; fetch can also take a default.
Why are symbols (:name) the conventional hash keys?
- They allow duplicates
- They sort automatically
- They're immutable and memory-efficient — every :name is the same object
- They are faster to type only
Answer: They're immutable and memory-efficient — every :name is the same object. Symbols are immutable and reused, so :name is always the same object — efficient for fixed keys.
Are and the same key?
- Yes, always
- No — a symbol and a string are different keys
- Only in Ruby 3
- Only for short strings
Answer: No — a symbol and a string are different keys. A symbol key and a string key are distinct; mixing them is a common source of nil surprises.
How do you iterate over key/value pairs of a hash?
- each { |k| }
- map { |v| }
- each_value { |k, v| }
- each { |k, v| }
Answer: each { |k, v| }. Use each with two block parameters: hash.each { |key, value| ... }.
What does return when :name exists?
- the value
- true
- nil
- the key
Answer: true. key? returns true or false depending on whether the key is present.
Since Ruby 1.9, what order does iterating a hash follow?
- Random order
- Sorted by key
- Insertion order
- Reverse order
Answer: Insertion order. Hashes preserve insertion order, so iteration visits pairs in the order they were added.