Question

How to Iterate Through an Array in Ruby: each, each_with_index, for, and More

rubyarraysloops

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_index gives |value, index| because the main thing in an array is the value.
  • Hash iteration with each gives |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.

Take Quiz

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 each for arrays most of the time
  • Use each_with_index when you need the index too
  • Use hash.each for 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:

  1. Ruby creates the array colors with three values.
  2. each_with_index starts looping through the array.
  3. On the first iteration:
    • color is "red"
    • index is 0
    • Ruby prints 0: red
  4. On the second iteration:
    • color is "green"
    • index is 1
    • Ruby prints 1: green
  5. On the third iteration:
    • color is "blue"
    • index is 2
    • Ruby prints 2: blue
  6. 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 0 up to colors.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.

Take Quiz

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:

  • each is for doing something with items
  • map is 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

MethodBest forBlock parametersIdiomatic?Notes
eachIterating values`value`
each_with_indexValue and index`value, index`
each_indexIndex only`index`
length.timesRepeating by count`i`
for ... inSimple looping`value` style variable

Arrays vs hashes

CollectionWhat it storesCommon iteration style
ArrayOrdered values`array.each {
Array with positionOrdered values plus index`array.each_with_index {
HashKey-value pairs`hash.each {

each_with_index vs each_index

MethodGives value?Gives index?Best choice when
each_with_indexYesYesYou need both
each_indexNoYesYou only need the index
Take Quiz

Cheat Sheet

Quick rules

  • Use array.each when you only need values.
  • Use array.each_with_index when you need both value and index.
  • Use array.each_index when you only need indexes.
  • Use hash.each for key-value pairs.
  • Use times for repeating a fixed number of times.
  • Prefer iterator methods over for in 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.

Take Quiz

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 Done or Pending based on the task status.
  • Print a summary count of completed tasks.
  • Use idiomatic Ruby iteration instead of manual index loops.
Take Quiz

Keep learning

Related questions

View more