Default values for missing keys in Ruby - Time & Space Complexity
When we use default values for missing keys in a hash, we want to know how this choice affects how long the program takes to run.
We ask: How does the time to find or set a default value change as the hash grows?
Analyze the time complexity of the following code snippet.
hash = Hash.new(0)
keys = ["a", "b", "c", "d", "e"]
keys.each do |key|
hash[key] += 1
end
value = hash["z"]
This code creates a hash with a default value of 0, counts keys, and accesses a missing key.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Looping over the keys array and accessing/updating the hash.
- How many times: Once for each key in the array (5 times here).
Each key is processed once, and each hash access is quick regardless of size.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 hash accesses and updates |
| 100 | About 100 hash accesses and updates |
| 1000 | About 1000 hash accesses and updates |
Pattern observation: The time grows directly with the number of keys processed.
Time Complexity: O(n)
This means the time to process keys grows in a straight line with the number of keys.
[X] Wrong: "Setting a default value makes hash lookups slower as the hash grows."
[OK] Correct: Hash lookups stay fast because Ruby hashes use efficient methods internally, so default values do not slow down access noticeably.
Understanding how default values affect hash access time helps you explain how data structures work efficiently in real programs.
"What if we changed the default value from a fixed number to a block that computes a value? How would the time complexity change?"
Practice
h = Hash.new(0)Solution
Step 1: Understand default value behavior
When a hash is created withHash.new(0), it sets 0 as the default value for any missing key.Step 2: Accessing a missing key
Accessing a key not present in the hash returns the default value 0 instead of nil.Final Answer:
Returns the default value instead of nil for missing keys -> Option AQuick Check:
Default value = 0 returned for missing keys [OK]
- Thinking missing keys raise errors
- Assuming missing keys return nil always
- Believing missing keys get added automatically
Solution
Step 1: Understand default block usage
Using a block withHash.newallows dynamic default values. To assign a new array to each missing key, the block must assign it to the hash.Step 2: Identify correct block syntax
The block receiveshashandkeyparameters and assigns[]tohash[key]. This ensures each missing key gets its own array.Final Answer:
h = Hash.new { |hash, key| hash[key] = [] } -> Option DQuick Check:
Block assigns new array to missing keys [OK]
- Using Hash.new([]) shares one array for all keys
- Using block without assigning to hash[key]
- Using wrong block parameters
h = Hash.new { |hash, key| hash[key] = [] }
h[:a] << 1
h[:b] << 2
p hSolution
Step 1: Understand default block behavior
The hash is created with a block that assigns an empty array to missing keys when accessed.Step 2: Modify arrays for keys :a and :b
Appending 1 toh[:a]creates:a => [1]. Similarly, appending 2 toh[:b]creates:b => [2].Step 3: Print the hash
Only keys :a and :b have values. No other keys exist.Final Answer:
{:a=>[1], :b=>[2]} -> Option CQuick Check:
Default arrays assigned and modified correctly [OK]
- Expecting keys not accessed to appear
- Confusing default value with nil
- Thinking default array is shared
h = Hash.new h.default = 0 puts h[:missing]
Solution
Step 1: Check default value assignment
Usingh.default = 0correctly sets the default value for missing keys after hash creation.Step 2: Access missing key
Accessingh[:missing]returns 0 as expected, no error occurs.Final Answer:
No error; code works and prints 0 -> Option BQuick Check:
Setting default after creation works [OK]
- Thinking default= is a syntax error
- Confusing default= with default_proc
- Expecting missing keys to raise errors
words = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple']
counter = ???
words.each { |w| counter[w] += 1 }
puts counterSolution
Step 1: Understand counting with default values
To count words, missing keys must return 0 socounter[w] += 1works. The+=reads the default 0, increments to 1, and assigns back, storing the key.Step 2: Compare options
Hash.new(0)returns 0 for missing keys (no store);+= 1stores the result. Perfect for counting.Hash.new { |h, k| [] }returns [];[] += 1TypeError.Hash.new([])returns shared []; TypeError.{}returnsnil; error.Final Answer:
counter = Hash.new(0) -> Option AQuick Check:
Hash.new(0) enables counter[w] += 1 [OK]
- Using block or Hash.new([]) returns array; TypeError on += 1
- Using {} with no default; nil error
- Wrong block parameters or no assignment
Ready to prove it?
Pass the test and this pattern moves unknown
