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"]

🧠 Test Your Knowledge

Which iterator would you use to transform an array of numbers by doubling each one?