Question
How to Iterate Through an Array in Ruby: each, each_with_index, for, and More
Question
In Ruby, what is the preferred or idiomatic way to iterate through an array?
In PHP, arrays and hashes are often treated similarly, and iteration commonly looks like this:
foreach ($arrayOrHash as $key => $value) {
// ...
}
In Ruby, there seem to be several different ways to iterate:
array.length.times do |i|
# ...
end
array.each do |value|
# ...
end
array.each_index do |i|
# ...
end
for value in array
# ...
end
For hashes, the pattern feels clearer:
hash.each do |key, value|
# ...
end
Why is array iteration different? Why not always use one style consistently? If I want both the index and value for an array, should I use each_index, or is there a better Ruby-style approach?
Also, Ruby provides each_with_index, but its block parameters are ordered as |value, index|, while hash.each uses |key, value|. Why is that, and what is considered idiomatic Ruby here?
Short Answer
By the end of this page, you will understand the idiomatic ways to loop through arrays in Ruby, when to use each, each_with_index, each_index, times, and for, and why Ruby treats arrays and hashes differently during iteration. You will also learn the common conventions used in real Ruby code so you can choose the clearest option for each situation.
Concept
Ruby has several ways to iterate because different collection types and different programming goals call for different tools.
The main idea is this:
- Arrays are ordered collections of values.
- Hashes are collections of key-value pairs.
Because they store different kinds of data, Ruby exposes different iteration styles for them.
For an array, the most natural thing is usually to work with each element directly:
numbers = [10, 20, 30]
numbers.each do |number|
puts number
end
For a hash, each element is naturally a pair:
user = { name: "Ava", age: 30 }
user.each do |key, value|
puts "#{key}: #{value}"
end
That is why array iteration usually yields one item, while hash iteration usually yields two.
Why this matters
In Ruby, the idiomatic style is to iterate at the highest level of meaning:
- If you need values, use
each - If you need value and index, use
each_with_index
Mental Model
Think of an array like a numbered row of boxes.
- If you only care about what is inside each box, walk along the row and open each box:
each - If you care about both the box number and what is inside it, carry both pieces of information:
each_with_index - If you only care about the box numbers, use
each_index
Now think of a hash like a dictionary.
Each entry is not just a value. It is a label and a value:
name => "Ava"age => 30
So when you iterate a hash, Ruby naturally gives you both the label and the value.
That is why arrays and hashes do not iterate in exactly the same way: they represent different shapes of data.
As for parameter order:
- Array iteration with
each_with_indexgives|value, index|because the main thing in an array is the value. - Hash iteration with
eachgives|key, value|because a hash entry is fundamentally a key-value pair.
Ruby is being consistent with the meaning of each collection, not forcing one universal loop format.
Syntax and Examples
Most common array iteration methods
each
Use this when you only need the value.
fruits = ["apple", "banana", "cherry"]
fruits.each do |fruit|
puts fruit.upcase
end
This is the most idiomatic choice for simple array iteration.
each_with_index
Use this when you need both the value and its position.
fruits = ["apple", "banana", "cherry"]
fruits.each_with_index do |fruit, index|
puts "#{index}: #{fruit}"
end
Notice the order: |value, index|.
each_index
Use this when you only need indexes.
fruits = ["apple", "banana", "cherry"]
fruits.each_index do ||
puts
Step by Step Execution
Consider this example:
colors = ["red", "green", "blue"]
colors.each_with_index do |color, index|
puts "#{index}: #{color}"
end
Here is what happens step by step:
- Ruby creates the array
colorswith three values. each_with_indexstarts looping through the array.- On the first iteration:
coloris"red"indexis0- Ruby prints
0: red
- On the second iteration:
coloris"green"indexis1- Ruby prints
1: green
- On the third iteration:
coloris
Real World Use Cases
Where array iteration is used in real programs
Rendering lists
products.each do |product|
puts product.name
end
Used in command-line apps, templates, and web views.
Showing numbered output
tasks.each_with_index do |task, index|
puts "#{index + 1}. #{task}"
end
Useful for menus, ranked results, or todo lists.
Validating imported data
rows.each_with_index do |row, index|
if row[:email].nil?
puts "Missing email on row #{index}"
end
end
Helpful in CSV imports and data-cleaning scripts.
Processing API results
responses.each do |response|
puts response[:status]
end
Common when handling JSON-like arrays of records.
Real Codebase Usage
In real Ruby codebases, developers usually choose iteration style based on intent.
Common patterns
1. Plain iteration with each
users.each do |user|
send_welcome_email(user)
end
Use this for side effects such as logging, sending emails, or saving records.
2. Index-aware iteration with each_with_index
errors.each_with_index do |error, index|
puts "Error #{index + 1}: #{error}"
end
Common for reporting, formatting, and diagnostics.
3. Guard clauses inside loops
users.each do |user|
next if user.email.nil?
send_email(user)
end
next skips invalid items and keeps the loop readable.
4. Validation during iteration
Common Mistakes
1. Using indexes when you only need values
Broken or less clear:
names.length.times do |i|
puts names[i]
end
Better:
names.each do |name|
puts name
end
Why: manual indexing adds noise and creates more chances for mistakes.
2. Confusing each with map
Broken idea:
upper = names.each do |name|
name.upcase
end
upper will still be the original array, not a transformed one.
Correct:
upper = names.map do |name|
name.upcase
end
3. Getting block parameter order wrong
Broken:
names.each_with_index do ||
puts
Comparisons
| Method | Best for | Block parameters | Idiomatic? | Notes |
|---|---|---|---|---|
each | Iterating values | ` | value | ` |
each_with_index | Value and index | ` | value, index | ` |
each_index | Index only | ` | index | ` |
length.times | Repeating by count | ` | i | ` |
Cheat Sheet
Quick rules
- Use
array.eachwhen you only need values. - Use
array.each_with_indexwhen you need both value and index. - Use
array.each_indexwhen you only need indexes. - Use
hash.eachfor key-value pairs. - Use
timesfor repeating a fixed number of times. - Prefer iterator methods over
forin idiomatic Ruby.
Common syntax
array.each do |value|
# ...
end
array.each_with_index do |value, index|
# ...
end
array.each_index do |index|
# ...
end
hash.each do |key, value|
# ...
end
FAQ
What is the most idiomatic way to iterate through an array in Ruby?
Usually each. It is the clearest choice when you only need the array's values.
When should I use each_with_index in Ruby?
Use it when you need both the element and its position in the array.
Is for bad in Ruby?
Not exactly. It is valid Ruby, but most Ruby code prefers each and other iterator methods.
Why does each_with_index use |value, index| instead of |index, value|?
Because the primary thing being iterated in an array is the value. The index is extra information.
Why does a hash use |key, value|?
Because each item in a hash is naturally a key-value pair.
Should I use each_index for arrays?
Only when you truly need just the index. If you need both index and value, each_with_index is usually clearer.
What is the difference between each and map in Ruby?
is for performing actions with elements. is for creating a new array from existing elements.
Mini Project
Description
Build a small command-line Ruby script that prints a numbered todo list and marks which tasks are complete. This project demonstrates the most common array iteration patterns: iterating values with each, iterating with positions using each_with_index, and iterating hash-like task data with each if you store task details as key-value pairs.
Goal
Create a Ruby script that displays a numbered list of tasks and shows each task's status clearly using idiomatic iteration methods.
Requirements
- Create an array of task hashes with a title and completed status.
- Print each task with its number using
each_with_index. - Display
DoneorPendingbased on the task status. - Print a summary count of completed tasks.
- Use idiomatic Ruby iteration instead of manual index loops.
Keep learning
Related questions
Calling a Class Method from an Instance in Ruby
Learn how to call a class method from an instance in Ruby using self.class, with examples, pitfalls, and practical usage patterns.
Calling an Overridden Monkey-Patched Method in Ruby
Learn how to call the original method when monkey patching in Ruby, including alias_method patterns, examples, pitfalls, and practical usage.
Convert a Unix Timestamp to Ruby DateTime
Learn how to convert Unix timestamps to Ruby DateTime and Time objects, with examples, differences, pitfalls, and practical Ruby usage.