Iterators are a core part of Ruby’s expressive style. Instead of writing manual loops, Ruby encourages you to iterate over collections using blocks, making code cleaner, safer, and more readable.
In this tutorial, you’ll learn the most important Ruby iterators with practical examples you can use right away.
Table of Contents
1) What Are Ruby Iterators?
An iterator is a method that loops through a collection and yields each element to a block.
Basic idea:
collection.iterator do |element|
# work with element
end
Common iterable objects in Ruby:
- Arrays
- Hashes
- Ranges
- Strings (in some cases)
- Enumerators
2) The each Iterator (Most Common)
Iterating over an Array
numbers = [1, 2, 3, 4, 5]
numbers.each do |n|
puts n * 2
end
Iterating over a Hash
person = { name: "Alice", age: 30, city: "Paris" }
person.each do |key, value|
puts "#{key}: #{value}"
end
One-line block syntax
numbers.each { |n| puts n }
3) The map / collect Iterator
map transforms each element and returns a new array.
numbers = [1, 2, 3, 4]
squared = numbers.map do |n|
n * n
end
puts squared.inspect
# => [1, 4, 9, 16]
Shorthand:
squared = numbers.map { |n| n * n }
4) The select and reject Iterators
select (filter values)
numbers = [1, 2, 3, 4, 5, 6]
evens = numbers.select { |n| n.even? }
puts evens.inspect
# => [2, 4, 6]
reject (opposite of select)
odds = numbers.reject { |n| n.even? }
puts odds.inspect
# => [1, 3, 5]
5) The reduce / inject Iterator
reduce combines all elements into a single value.
Sum of numbers
numbers = [1, 2, 3, 4]
sum = numbers.reduce(0) do |total, n|
total + n
end
puts sum
# => 10
Shorthand with symbol
sum = numbers.reduce(:+)
puts sum
6) The each_with_index Iterator
Useful when you need both the value and its position.
fruits = ["apple", "banana", "cherry"]
fruits.each_with_index do |fruit, index|
puts "#{index}: #{fruit}"
end
7) The times, upto, and downto Iterators
times
3.times do |i|
puts "Iteration #{i}"
end
upto
1.upto(5) do |n|
puts n
end
downto
5.downto(1) do |n|
puts n
end
8) The each_slice and each_cons Iterators
each_slice (chunks)
numbers = [1, 2, 3, 4, 5, 6]
numbers.each_slice(2) do |slice|
p slice
end
# => [1, 2]
# => [3, 4]
# => [5, 6]
each_cons (sliding window)
numbers.each_cons(3) do |group|
p group
end
# => [1, 2, 3]
# => [2, 3, 4]
# => [3, 4, 5]
# => [4, 5, 6]
9) Iterators Without a Block (Enumerators)
If you don’t pass a block, many iterators return an Enumerator.
enum = [1, 2, 3].each
puts enum.next
puts enum.next
puts enum.next
Chaining:
result = [1, 2, 3, 4, 5]
.select(&:odd?)
.map { |n| n * 10 }
puts result.inspect
# => [10, 30, 50]
10) Custom Iterators with yield
You can create your own iterators using yield.
def repeat_three_times
3.times do
yield
end
end
repeat_three_times do
puts "Hello!"
end
With parameters:
def countdown(from)
from.downto(1) do |n|
yield n
end
end
countdown(3) { |n| puts n }
11) When to Use Iterators vs Loops
| Use Case | Recommended |
|---|---|
| Transform data | map |
| Filter data | select, reject |
| Accumulate values | reduce |
| Side effects only | each |
| Simple counting | times, upto |
Ruby iterators are preferred over for or while loops for clarity and safety.
FAQ
Q: What is an iterator in Ruby? A: An iterator is a method that loops through a collection and yields each element to a block.
Q: What is the difference between each and map? A: each is used for side effects, while map returns a new array with transformed values.
Q: Are Ruby iterators faster than loops? A: Performance is usually similar, but iterators are preferred for readability and idiomatic Ruby code.