Ruby Iterators
Ruby's elegant way to loop through collections
🎯 What are Ruby Iterators?
Iterators are Ruby's powerful methods for looping through collections. They're more elegant and flexible than traditional loops, making your code cleaner and more expressive. They're the Ruby way!
# Simple iterator example
[1, 2, 3].each do |number|
puts "Number: #{number}"
end
Output:
Number: 1 Number: 2 Number: 3
Common Ruby Iterators
each
Basic iteration over elements
[1, 2, 3].each do |n|
puts n
end
map
Transform each element
[1, 2, 3].map do |n|
n * 2
end
# [2, 4, 6]
select
Filter elements by condition
[1, 2, 3, 4].select do |n|
n.even?
end
# [2, 4]
reduce
Combine elements into single value
[1, 2, 3].reduce(0) do |sum, n|
sum + n
end
# 6
🔹 The each Iterator
The each iterator is the most fundamental and commonly used. It executes a block of code for each element in a collection without modifying the original collection.
# each with array
fruits = ["apple", "banana", "cherry"]
fruits.each do |fruit|
puts "I love #{fruit}s!"
end
# each with range
(1..3).each do |num|
puts "Count: #{num}"
end
# each with hash
person = { name: "Alice", age: 25 }
person.each do |key, value|
puts "#{key}: #{value}"
end
Output:
I love apples! I love bananas! I love cherrys! Count: 1 Count: 2 Count: 3 name: Alice age: 25
🔹 The map Iterator
The map iterator transforms each element and returns a new array with the transformed values. It's perfect when you need to convert or modify every element.
# Double each number
numbers = [1, 2, 3, 4]
doubled = numbers.map do |num|
num * 2
end
puts "Original: #{numbers}"
puts "Doubled: #{doubled}"
# Convert to uppercase
words = ["hello", "world"]
uppercase = words.map { |word| word.upcase }
puts "Uppercase: #{uppercase}"
# Calculate squares
squares = [1, 2, 3, 4, 5].map { |n| n ** 2 }
puts "Squares: #{squares}"
Output:
Original: [1, 2, 3, 4] Doubled: [2, 4, 6, 8] Uppercase: ["HELLO", "WORLD"] Squares: [1, 4, 9, 16, 25]
🔹 The select Iterator
The select iterator filters elements based on a condition. It returns a new array containing only elements for which the block returns true.
# Select even numbers
numbers = [1, 2, 3, 4, 5, 6]
evens = numbers.select { |num| num.even? }
puts "Even numbers: #{evens}"
# Select long words
words = ["hi", "hello", "hey", "goodbye"]
long_words = words.select { |word| word.length > 3 }
puts "Long words: #{long_words}"
# Select positive numbers
values = [-2, 5, -1, 8, 0, 3]
positives = values.select { |n| n > 0 }
puts "Positive: #{positives}"
Output:
Even numbers: [2, 4, 6] Long words: ["hello", "goodbye"] Positive: [5, 8, 3]
🔹 The reduce Iterator
The reduce iterator (also called inject) combines all elements into a single value. It's commonly used for summing, multiplying, or accumulating values.
# Sum all numbers
numbers = [1, 2, 3, 4, 5]
sum = numbers.reduce(0) { |total, num| total + num }
puts "Sum: #{sum}"
# Multiply all numbers
product = [2, 3, 4].reduce(1) { |result, num| result * num }
puts "Product: #{product}"
# Find maximum
max = [3, 7, 2, 9, 1].reduce { |max, num| num > max ? num : max }
puts "Maximum: #{max}"
# Concatenate strings
words = ["Hello", " ", "World"]
sentence = words.reduce("") { |result, word| result + word }
puts "Sentence: #{sentence}"
Output:
Sum: 15 Product: 24 Maximum: 9 Sentence: Hello World
🔹 Other Useful Iterators
Ruby provides many more iterators for specific tasks. Here are some commonly used ones:
# reject - opposite of select
numbers = [1, 2, 3, 4, 5]
odds = numbers.reject { |n| n.even? }
puts "Odds: #{odds}"
# find - returns first matching element
first_even = [1, 3, 4, 5, 6].find { |n| n.even? }
puts "First even: #{first_even}"
# count - count matching elements
even_count = [1, 2, 3, 4, 5, 6].count { |n| n.even? }
puts "Even count: #{even_count}"
# any? - check if any element matches
has_even = [1, 3, 5, 6].any? { |n| n.even? }
puts "Has even: #{has_even}"
# all? - check if all elements match
all_positive = [1, 2, 3, 4].all? { |n| n > 0 }
puts "All positive: #{all_positive}"
Output:
Odds: [1, 3, 5] First even: 4 Even count: 3 Has even: true All positive: true
🔹 Block Syntax Variations
Ruby offers two ways to write blocks with iterators: do...end for multi-line blocks and curly braces {} for one-liners:
# Multi-line block with do...end
[1, 2, 3].each do |num|
square = num ** 2
puts "#{num} squared is #{square}"
end
# One-line block with curly braces
[1, 2, 3].each { |num| puts num * 2 }
# Both styles work the same way!
# Use do...end for multiple lines
# Use {} for single line operations
Output:
1 squared is 1 2 squared is 4 3 squared is 9 2 4 6
🔹 Chaining Iterators
One of Ruby's most powerful features is the ability to chain multiple iterators together for complex operations:
# Chain select and map
numbers = [1, 2, 3, 4, 5, 6]
result = numbers.select { |n| n.even? }.map { |n| n ** 2 }
puts "Even squares: #{result}"
# Chain multiple operations
words = ["hello", "world", "ruby", "code"]
result = words
.select { |w| w.length > 4 }
.map { |w| w.upcase }
.sort
puts "Filtered words: #{result}"
Output:
Even squares: [4, 16, 36] Filtered words: ["HELLO", "WORLD"]