Array#each_index
array.each_index { |index| block } -> array each_index iterates over an array by passing each element’s index to the block, rather than the element itself. This is the difference from Array#each, which passes elements.
Syntax
array.each_index { |index| block } -> array
array.each_index -> Enumerator
Examples
Basic Usage
fruits = ["apple", "banana", "cherry"]
fruits.each_index { |i| puts "Index: #{i}" }
# Index: 0
# Index: 1
# Index: 2
# => ["apple", "banana", "cherry"]
each_index vs each
This shows the key difference:
letters = ["a", "b", "c"]
# each gives you the element
letters.each { |elem| puts elem }
# a
# b
# c
# each_index gives you the index
letters.each_index { |i| puts i }
# 0
# 1
# 2
Building an index table
users = ["Alice", "Bob", "Carol"]
users.each_index { |i| puts "#{i + 1}. #{users[i]}" }
# 1. Alice
# 2. Bob
# 3. Carol
Accessing elements by index during iteration
names = ["John", "Jane", "Jim"]
ages = [30, 25, 40]
names.each_index { |i| puts "#{names[i]} is #{ages[i]}" }
# John is 30
# Jane is 25
# Jim is 40
Modifying array elements at specific indices
numbers = [1, 2, 3, 4, 5]
# Double every element at even index
numbers.each_index { |i| numbers[i] *= 2 if i.even? }
numbers
# => [2, 2, 6, 4, 10]
With with_index (same pattern as each)
items = ["Alpha", "Beta", "Gamma"]
items.each_index.with_index(1) { |idx, num| puts "#{num}. #{idx}" }
# 1. 0
# 2. 1
# 3. 2
Return Value
each_index returns the array itself:
arr = [10, 20, 30]
result = arr.each_index { |i| puts i }
result.object_id == arr.object_id # => true
When called without a block, it returns an Enumerator:
[1, 2, 3].each_index
# => #<Enumerator: [1, 2, 3]:each_index>
Common use cases
Parallel array iteration
When you have two arrays and need to iterate through them together by position:
products = ["Widget", "Gadget", "Gizmo"]
prices = [100, 50, 75]
products.each_index do |i|
puts "#{products[i]}: $#{prices[i]}"
end
# Widget: $100
# Gadget: $50
# Gizmo: $75
Selective processing by index
data = [1, 2, 3, 4, 5]
# Process only even indices
data.each_index { |i| data[i] *= 10 if i.even? }
# => [10, 2, 30, 4, 50]
Building numbered output
tasks = ["Write tests", "Deploy app", "Update docs"]
tasks.each_index do |i|
puts "[ ] #{i + 1}. #{tasks[i]}"
end
# [ ] 1. Write tests
# [ ] 2. Deploy app
# [ ] 3. Update docs
When to Use each_index vs each_with_index
| Method | Yields | Use When |
|---|---|---|
each_index | Index only | You don’t need the element |
each_with_index | Element and index | You need both values |
each | Element only | Index is irrelevant |
If you need both element and index, each_with_index is often cleaner:
items = ["a", "b", "c"]
# With each_index - you fetch the element manually
items.each_index { |i| puts "#{i}: #{items[i]}" }
# With each_with_index - cleaner
items.each_with_index { |item, i| puts "#{i}: #{item}" }
For cases where you only need the index (not the element), each_index makes the intent explicit.
Performance
each_index has the same performance characteristics as each. There’s no meaningful overhead difference. Choose based on clarity of intent, not performance.
See Also
- Enumerable#each_with_index — iterate with both element and index
- Array#each_slice — iterate over fixed-size groups
- Array#map — transform array elements