Hashes in Ruby

· 5 min read · Updated March 7, 2026 · beginner
hashes key-value data-structures beginner

Hashes are one of the most versatile and frequently used data structures in Ruby. If you’ve worked with dictionaries in Python or objects in JavaScript, you’ll feel right at home with Ruby hashes.

In this tutorial, you’ll learn what hashes are, how to create them, and how to use them effectively in your Ruby programs.

What is a Hash?

A hash (also called an associative array or dictionary in other languages) is a collection of key-value pairs. Unlike arrays, which use numeric indices, hashes let you access values using custom keys.

# A simple hash representing a user's information
user = {
  "name" => "Alice",
  "age" => 30,
  "city" => "London"
}

Each key maps to a value, and you can retrieve any value instantly using its key—regardless of where it appears in the hash.

Creating Hashes

There are several ways to create a hash in Ruby:

# Using curly braces (most common)
person = { "name" => "Bob", "occupation" => "Developer" }

# Using the Hash.new constructor
scores = Hash.new

# With a default value
zeros = Hash.new(0)  # Default value is 0

# Using symbols as keys (recommended for better performance)
config = {
  :debug => true,
  :timeout => 30
}

# Modern symbol syntax (Ruby 1.9+)
settings = {
  theme: "dark",
  language: "en"
}

Pro tip: Using symbols as keys is the Ruby convention and offers better memory efficiency than strings.

Accessing Values

Retrieve values from a hash using bracket notation:

user = { name: "Charlie", age: 25, city: "Paris" }

puts user[:name]    # => "Charlie"
puts user[:age]     # => 25
puts user[:country] # => nil

# Using fetch - raises error if key missing
puts user.fetch(:name)    # => "Charlie"
puts user.fetch(:country, "Unknown") # => "Unknown" (with default)

The fetch method is safer when you’re unsure whether a key exists—it lets you provide a default value or handle missing keys explicitly.

Modifying Hashes

Ruby provides many ways to add, update, and remove hash entries:

book = { title: "The Great Gatsby", author: "F. Scott Fitzgerald" }

# Adding new key-value pairs
book[:year] = 1925
book[:pages] = 180

# Updating existing values
book[:author] = "F. Scott Fitzgerald (Updated Edition)"

# Removing keys
book.delete(:pages)

# Clear all entries
# book.clear

Useful Modification Methods

inventory = { apples: 5, bananas: 3, oranges: 8 }

# Merge two hashes (keys from other hash overwrite duplicate keys)
more_fruit = { bananas: 10, grapes: 15 }
inventory.merge!(more_fruit)

puts inventory
# => { apples: 5, bananas: 10, oranges: 8, grapes: 15 }

# Only keep certain keys
user_data = { name: "Diana", email: "diana@example.com", age: 28, city: "NYC" }
user_data.slice!(:name, :email)
# => { name: "Diana", email: "diana@example.com" }

Iterating Over Hashes

One of the most powerful features of hashes is the ability to iterate over key-value pairs:

prices = { coffee: 4, tea: 3, soda: 2 }

# Iterate over each key-value pair
prices.each do |key, value|
  puts "#{key}: $#{value}"
end

# Output:
# coffee: $4
# tea: $3
# soda: $2

# Iterate over only keys
prices.each_key { |key| puts key }

# Iterate over only values
prices.each_value { |value| puts value }

# With index
prices.each_with_index do |(key, value), index|
  puts "#{index + 1}. #{key} = #{value}"
end

Common Hash Methods

Ruby hashes come with many built-in methods that make common operations trivial:

movie = { title: "Inception", year: 2010, director: "Christopher Nolan" }

# Check if hash has a key
movie.key?(:title)      # => true
movie.has_key?(:rating) # => false

# Check if hash has a value
movie.value?("Inception") # => true

# Get all keys or values as arrays
movie.keys    # => [:title, :year, :director]
movie.values  # => ["Inception", 2010, "Christopher Nolan"]

# Hash size
movie.length  # => 3
movie.size    # => 3
movie.empty?  # => false

# Check if empty
{}.empty?     # => true

Practical Examples

Counting Occurrences

Hashes are perfect for counting things:

# Count letter frequency in a string
text = "hello world"
frequency = Hash.new(0)

text.each_char do |char|
  frequency[char] += 1
end

puts frequency
# => {"h"=>1, "e"=>1, "l"=>3, "o"=>2, " "=>1, "w"=>1, "r"=>1, "d"=>1}

Grouping Data

# Group people by age
people = [
  { name: "Alice", age: 30 },
  { name: "Bob", age: 25 },
  { name: "Charlie", age: 30 }
]

grouped = people.group_by { |person| person[:age] }

puts grouped
# => {30=>[{:name=>"Alice", :age=>30}, {:name=>"Charlie", :age=>30}],
#     25=>[{:name=>"Bob", :age=>25}]}

Handling Options

Hashes are commonly used to pass optional parameters to methods:

def create_user(name, options = {})
  defaults = { age: 18, role: "user", active: true }
  settings = defaults.merge(options)
  
  puts "Creating user: #{name}"
  puts "  Age: #{settings[:age]}"
  puts "  Role: #{settings[:role]}"
  puts "  Active: #{settings[:active]}"
end

create_user("Emma")
create_user("Frank", age: 25, role: "admin")

When to Use Hashes

Use hashes when you need:

  • Key-value associations (like a dictionary)
  • Fast lookups by custom keys
  • Grouping related data together
  • Counting or aggregating items

Consider alternatives when you need:

  • Ordered sequences → use Arrays
  • Unique values only → use Sets
  • Numeric indexing → use Arrays

Summary

Hashes are essential in Ruby programming. They provide fast key-based access to data and support powerful operations like merging, filtering, and transforming.

Key takeaways:

  • Use symbols as keys for better performance
  • Access values with hash[key] or hash.fetch(key, default)
  • Iterate with each, each_key, or each_value
  • Use built-in methods like merge, slice, and group_by for common tasks

Now that you understand hashes, you’re ready to explore Blocks and Iterators—Ruby’s powerful way of passing executable code around.