Skip to content

Ruby Hashes

A Hash in Ruby is a collection of key-value pairs, also known as an associative array or dictionary. It’s similar to an Array, but indexing is done using arbitrary keys (any object type) rather than integer indices.

As of Ruby 1.9, Hashes maintain insertion order. When you iterate over a hash, the key-value pairs are yielded in the order they were originally inserted. If you attempt to access a hash with a key that does not exist, it typically returns nil (unless a default value or block is specified).

There are several ways to create hashes:

// 1. Using Hash literal syntax (most common)
empty_hash = {}
name_to_age = { "Alice" => 30, "Bob" => 25, "Charlie" => 35 }
// 2. Using the new "rocketless" syntax for Symbol keys (Ruby 1.9+)
// This is very common, especially with keyword arguments.
symbol_keyed_hash = { name: "David", age: 40, city: "New York" }
// Equivalent to: { :name => "David", :age => 40, :city => "New York" }
// 3. Using Hash.new to create an empty hash
months = Hash.new
// 4. Using Hash.new with a default value (returned for non-existent keys)
default_value_hash = Hash.new(0) # Accessing a missing key returns 0
puts default_value_hash["non_existent_key"] # => 0
// 5. Using Hash.new with a block to compute default values dynamically
// The block is executed each time an unknown key is accessed.
dynamic_default_hash = Hash.new { |hash, key| hash[key] = "Default for #{key}" }
puts dynamic_default_hash["first_try"] # => "Default for first_try"
puts dynamic_default_hash["first_try"] # Now it exists, so it returns the stored value.
puts dynamic_default_hash.inspect # => {"first_try"=>"Default for first_try"}
// 6. Using Hash[] class method (less common for literals)
coordinates = Hash[:x, 10, :y, 20, :z, 5]
// Equivalent to: { :x => 10, :y => 20, :z => 5 }

Keys and values in a Hash can be of any object type. However, keys must be unique. If you assign a value to an existing key, the old value is overwritten.

Common Key Types: Symbols (:my_key) are often preferred for keys because they are immutable and memory-efficient. Strings ("my_key") are also common.

Hashes have a rich set of methods for manipulation. Assuming my_hash is a Hash object:

#!/usr/bin/env ruby
# frozen_string_literal: true
months = { "1" => "January", "2" => "February", "3" => "March" }
# Get all keys
keys = months.keys
puts "Keys: #{keys.inspect}" # Output: Keys: ["1", "2", "3"]
# Get all values
values = months.values
puts "Values: #{values.inspect}" # Output: Values: ["January", "February", "March"]
# Iterate over key-value pairs
months.each do |key, value|
puts "Month number #{key} is #{value}"
end

Below are some common public Hash methods. For a complete list, refer to the official Ruby documentation.

IDMethod and Description
1hash == other_hash
Tests if two hashes are equal: same number of key-value pairs, and each key/value pair is equal (==).
2hash[key]
Accesses the value associated with key. Returns nil or the default value/block result if the key is not found.
3hash[key] = value
Associates value with key. Overwrites existing value if key exists. Alias: store.
4hash.clear
Removes all key-value pairs from hash, making it empty.
5hash.default(key = nil)
Returns the default value for hash (the value that hash[key] would return if key is not found).
6hash.default = obj
Sets the default value that is returned for accesses to keys not present in the hash.
7hash.default_proc
Returns the block if hash was created with a default block; otherwise, returns nil.
8hash.delete(key) or hash.delete(key) { |k| block_value }
Deletes the key-value pair specified by key. Returns the value associated with the key. If the key is not found, returns nil, or executes the block and returns its result if provided.
9hash.delete_if { |key, value| block_condition }
Deletes key-value pairs for which the block evaluates to true. Returns the hash. Also reject! (destructive).
10hash.each { |key, value| block } or hash.each_pair { |key, value| block }
Iterates over the hash, yielding each key-value pair to the block. Returns an Enumerator if no block is given.
11hash.each_key { |key| block }
Iterates over the hash, yielding each key to the block. Returns an Enumerator if no block is given.
12hash.each_value { |value| block }
Iterates over the hash, yielding each value to the block. Returns an Enumerator if no block is given.
13hash.empty?
Returns true if the hash contains no key-value pairs.
14hash.fetch(key [, default_value]) or hash.fetch(key) { |k| block_value }
Returns the value for key. If key is not found, raises KeyError. If default_value is given, it’s returned instead. If a block is given, its result is returned.
15hash.key?(key) or hash.has_key?(key) or hash.include?(key) or hash.member?(key)
Returns true if the given key is present in the hash.
16hash.value?(value) or hash.has_value?(value)
Returns true if the given value is present in the hash.
17hash.key(value)
Returns the key for the first occurrence of the given value. Returns nil if no matching value is found.
18hash.invert
Returns a new hash created by inverting keys and values from hash. If duplicate values exist, one of the corresponding keys will be chosen as the new value (behavior for which one may vary).
19hash.keys
Returns a new array containing all the keys from hash.
20hash.length or hash.size
Returns the number of key-value pairs in the hash as an integer.
21hash.merge(other_hash) or hash.merge(other_hash) { |key, old_val, new_val| block_value }
Returns a new hash containing the contents of hash and other_hash. If a key exists in both, the value from other_hash is used, unless a block is provided to resolve conflicts.
22hash.merge!(other_hash) or hash.merge!(other_hash) { |key, old_val, new_val| block_value }
Same as merge, but modifies hash in place. Alias: update.
23hash.rehash
Rebuilds the hash based on the current hash values for each key. Needed if mutable keys have changed their hash value since insertion.
24hash.reject { |key, value| block_condition }
Returns a new hash containing only key-value pairs for which the block evaluates to false or nil.
25hash.reject! { |key, value| block_condition }
Same as reject, but modifies hash in place. Returns hash or nil if no changes were made.
26hash.replace(other_hash)
Replaces the contents of hash with the contents of other_hash.
27hash.select { |key, value| block_condition }
Returns a new hash containing only key-value pairs for which the block evaluates to true.
28hash.select! { |key, value| block_condition }
Same as select, but modifies hash in place. Returns hash or nil if no changes were made.
29hash.shift
Removes the first key-value pair from hash (based on insertion order) and returns it as a two-element array [key, value]. Returns nil or default if hash is empty.
30hash.slice(*keys)
Returns a new hash containing only the key-value pairs for the specified keys (Ruby 2.5+).
31hash.transform_keys { |key| new_key }
Returns a new hash where keys are transformed by the block.
32hash.transform_keys! { |key| new_key }
Same as transform_keys, but modifies hash in place.
33hash.transform_values { |value| new_value }
Returns a new hash where values are transformed by the block.
34hash.transform_values! { |value| new_value }
Same as transform_values, but modifies hash in place.
35hash.sort or hash.sort { |(k1,v1), (k2,v2)| block_comparison }
Converts hash to a nested array of [key, value] pairs and sorts it. Default sort is by key. A block can be provided for custom sorting logic.
36hash.to_a
Converts hash to a nested array, where each inner array is a [key, value] pair.
37hash.to_h or hash.to_hash
Returns self (the hash itself). Useful for converting array-like objects that implement to_h.
38hash.to_s or hash.inspect
Returns a string representation of the hash, typically suitable for printing or debugging.
39hash.values
Returns a new array containing all the values from hash.
40hash.values_at(key1, key2, …)
Returns a new array containing the values associated with the given keys. If a key is not found, nil (or the default value) is used for that position in the array.