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 - If you need only indexes, use
each_index - If you need to repeat something a fixed number of times, use
times
This matters because code becomes:
- easier to read
- less error-prone
- more expressive
- more aligned with Ruby conventions
For example, this works, but is less idiomatic when you only need values:
array.length.times do |i|
puts array[i]
end
Ruby programmers usually prefer:
array.each do |value|
puts value
end
The second version says exactly what you mean: “for each value.” It avoids manual indexing unless indexing is actually part of the task.
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 |index|
puts "Index: #{index}"
end
If you immediately write fruits[index] inside the block, each_with_index is often clearer.
times
Use this when you want to repeat something a known number of times.
3.times do |i|
puts "Run #{i}"
end
You can use it with array length, but that is usually less expressive than each.
fruits.length.times do |i|
puts fruits[i]
end
for
Ruby supports for, but it is less commonly used than each.
for fruit in fruits
puts fruit
end
In idiomatic Ruby, iterator methods such as each are usually preferred.
Hash iteration syntax
user = { name: "Ava", age: 30 }
user.each do |key, value|
puts "#{key} = #{value}"
end
Best beginner rule
- Use
eachfor arrays most of the time - Use
each_with_indexwhen you need the index too - Use
hash.eachfor hashes
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"blue"indexis2- Ruby prints
2: blue
- The loop ends after the last element.
Output:
0: red
1: green
2: blue
Compare that with index-based looping:
colors.length.times do |i|
puts "#{i}: #{colors[i]}"
end
This produces the same result, but Ruby has to:
- count from
0up tocolors.length - 1 - use the index to look up each value
That is why each_with_index is usually clearer when you need both pieces of information.
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.
Working with hash data
settings.each do |key, value|
puts "#{key}: #{value}"
end
Useful for configuration, metadata, and dynamic attributes.
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
params.each do |key, value|
raise "Missing value for #{key}" if value.nil?
end
Often used when checking incoming request data or configuration.
5. Transforming data with map instead of each
If you are building a new array, developers often use map rather than each.
names = users.map do |user|
user.name.upcase
end
This is an important distinction:
eachis for doing something with itemsmapis for creating a new collection
6. Filtering with select
active_users = users.select do |user|
user.active?
end
Real projects often combine iterable methods instead of manual index loops.
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 |index, name|
puts "#{index}: #{name}"
end
Correct:
names.each_with_index do |name, index|
puts "#{index}: #{name}"
end
For arrays, the order is value, index.
4. Using for expecting it to behave like other languages
for works, but Ruby programmers often prefer each and related iterator methods because they fit Ruby's object-oriented style better.
5. Accessing invalid indexes
Broken:
names = ["Ava", "Ben"]
3.times do |i|
puts names[i].upcase
end
When i becomes 2, names[2] is nil, and nil.upcase fails.
Safer:
names.each do |name|
puts name.upcase
end
6. Using each_index when each_with_index is clearer
Less clear:
names.each_index do |i|
puts "#{i}: #{names[i]}"
end
Clearer:
names.each_with_index do |name, i|
puts "#{i}: #{name}"
end
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 | ` |
for ... in | Simple looping | ` | value | ` style variable |
Arrays vs hashes
| Collection | What it stores | Common iteration style |
|---|---|---|
| Array | Ordered values | `array.each { |
| Array with position | Ordered values plus index | `array.each_with_index { |
| Hash | Key-value pairs | `hash.each { |
each_with_index vs each_index
| Method | Gives value? | Gives index? | Best choice when |
|---|---|---|---|
each_with_index | Yes | Yes | You need both |
each_index | No | Yes | You only need the index |
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
3.times do |i|
# ...
end
Parameter order to remember
array.each_with_index→|value, index|hash.each→|key, value|
Good default choices
- Array values only:
each - Array values + index:
each_with_index - Hash entries:
each
Edge case reminder
If you use indexes manually, accessing an out-of-range position returns nil:
arr = [1, 2]
p arr[5] # nil
That can cause errors if you call methods on the result.
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?
each is for performing actions with elements. map is for creating a new array from existing elements.
Can I iterate arrays and hashes the same way in Ruby?
Not exactly, because they represent different kinds of data. Arrays hold ordered values; hashes hold key-value pairs.
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
Add a Default Value to an Existing Column in a Rails Migration
Learn how to add or change a default value on an existing database column using Rails Active Record migrations safely.
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.