Hashes
11.1 Creating Hashes
person = { name: "Ana", age: 30 } # symbol keys (modern syntax)
legacy = { "name" => "Ana", 1 => "one" } # any object as a key (hash rocket)
empty = {}
with_default = Hash.new(0) # default value for missing keys
counts = Hash.new { |h, k| h[k] = [] } # default block (safe for mutable defaults)
pairs = [[:a, 1], [:b, 2]].to_h
x = 1; y = 2
point = { x:, y: } # shorthand (Ruby 3.1): { x: 1, y: 2 }11.2 Accessing and Modifying
person[:name] # "Ana"
person[:missing] # nil
person.fetch(:age) # raises KeyError if missing
person.fetch(:email, "n/a")
person.fetch(:email) { |k| "no #{k}" }
person.dig(:address, :city) # safe nested access
person[:email] = "[email protected]"
person.store(:city, "Pune")
person.delete(:city)
person.key?(:name); person.value?(30); person.include?(:age)
person.keys; person.values; person.size; person.empty?
person.to_a; person.invert; person.key(30)
person.merge(country: "IN")
person.merge!(other) { |key, old, new| old + new } # conflict resolution
person.update(age: 31)
person.slice(:name, :age); person.except(:age)
person.values_at(:name, :age)
person.default = "unknown"
person.compare_by_identity
person.compact # remove nil values
person.sort_by { |k, v| v.to_s }.to_h
person.min_by { |k, v| v.to_s }
person.to_a.flatten11.3 Iterating and Transforming
Hashes preserve insertion order (since Ruby 1.9).
Symbol vs string keys are different keys: h[:a] ≠ h["a"]. (Rails provides HashWithIndifferentAccess.)
Ruby 3.4 changed Hash#inspect output: {name: "Ana", "key" => 1}.
prices = { apple: 1.2, banana: 0.5, cherry: 3.0 }
prices.each { |fruit, price| puts "#{fruit}: $#{price}" }
prices.each_pair { |k, v| }
prices.each_key { |k| }; prices.each_value { |v| }
prices.map { |k, v| [k, v * 2] }.to_h
prices.transform_values { |v| (v * 1.18).round(2) }
prices.transform_keys(&:to_s)
prices.select { |k, v| v > 1 } # also filter, reject
prices.filter_map { |k, v| k if v > 1 }
prices.find { |k, v| v < 1 }
prices.sum { |k, v| v }
prices.count { |k, v| v > 1 }
prices.any? { |k, v| v > 2 }
prices.sort_by { |_, v| -v }.first(2)
prices.max_by { |_, v| v }
prices.group_by { |_, v| v > 1 ? :expensive : :cheap }
prices.each_with_object({}) { |(k, v), acc| acc[v] = k }
prices.reduce(0) { |sum, (_, v)| sum + v }
prices.to_a.each_slice(2).map(&:to_h)
words.tally.sort_by(&:last).reverse # word frequency