Working with hashes in Ruby
Short answer
Access with hash[:key] or fetch for a required key. Iterate with each taking two block parameters. Hash.new(0) gives you a counting hash for free.
lessons = { python: 4, php: 5, ruby: 1 }
lessons[:python] # 4
lessons[:missing] # nil
lessons.fetch(:missing) # KeyError — good when it must exist
lessons.fetch(:missing, 0) # 0#Iterating
lessons.each { |track, count| puts "#{track}: #{count}" }
lessons.each_key { |k| puts k }
lessons.each_value { |v| puts v }Enumerable methods work, with pairs going in and pairs coming out:
lessons.select { |_, count| count > 2 } # {python: 4, php: 5}
lessons.reject { |_, count| count > 2 } # {ruby: 1}
lessons.max_by { |_, count| count } # [:php, 5]
lessons.sum { |_, count| count } # 10
lessons.sort_by { |_, count| -count } # array of pairsThe underscore is the convention for a parameter you must accept but do not use.
#Transforming
lessons.transform_values { |v| v * 2 }
lessons.transform_keys(&:to_s)
lessons.filter_map { |k, v| k if v > 2 } # [:python, :php]filter_map combines select and map in one pass — it keeps whatever the block returns, skipping nil and false.
#Default values
counts = Hash.new(0)
words.each { |w| counts[w] += 1 }Any missing key reads as 0, so += works without checking first. For a default that is a fresh object each time, use the block form:
groups = Hash.new { |h, k| h[k] = [] }
groups[:python] << "Intro"#Merging
defaults.merge(overrides) # right side wins
a.merge(b) { |_, old, new| old + new } # resolve conflicts yourself