In programming, we often need to go through a list of values one at a time. For example, we may want to print each item in a collection (array, hash, etc.) or add numbers in a range.
Ruby provides two primary ways to do this:
- The
for
loop - The
each
loop
Both loops are used to go through (iterate over) each item in a collection or a range.
Let's explore each of them and see how they're related, starting with the for loop.
Ruby for Loop
The for
loop is used to iterate over a range or a collection (like arrays or hashes), one at a time. Its syntax is:
for variable in collection
# Code to execute
end
Here,
collection
- A range of values, or a collection of values like arrays or hashes.variable
- A placeholder that takes the value of each element in thecollection
during each iteration.
Here's how it works:
- The
for
loop iterates over the elements of thecollection
. - In every iteration, the
variable
takes the value of the currentcollection
element. It is then reassigned to the next element in the following iteration. - The loop ends once all the elements have been iterated over.
Note: Many Ruby programmers prefer the each
loop over the for
loop when iterating over collections.
Example 1: Ruby for Loop with Range
for num in 4..6
puts num
end
Output
4 5 6
Here, the for
loop iterates over the range 4..6
. As a result, the loop runs three times over the numbers 4, 5, and 6.
In each iteration of the loop, the variable num
takes values from 4 to 6, which is then printed to the screen. Here's how it works:
Loop Iteration | Value of num |
---|---|
First | 4 |
Second | 5 |
Third | 6 |
Example 2: Ruby for Loop with Array
people = ["Bob", "Alex", "Sharon", "Cassie"]
for person in people
puts person
end
Output
Bob Alex Sharon Cassie
Here, the for
loop iterates over the people
array. In each iteration of the loop, the variable person
takes the corresponding element of the array. Here's how this works:
Loop Iteration | Value of person |
---|---|
1 | "Bob" |
2 | "Alex" |
3 | "Sharon" |
4 | "Cassie" |
Example 3: Ruby for Loop with Hash
# Create a hash named 'person'
# "name", "age", and "city" are keys
# "Alice", 30, and "Paris" are the corresponding values
person = { "name" => "Alice", "age" => 30, "city" => "Paris" }
for key, value in person
puts "#{key}: #{value}"
end
Output
name: Alice age: 30 city: Paris
In this example, we created a hash named person
. Then, we used a for
loop to iterate over the hash.
In each iteration of the loop, the key
and value
variables of the loop take a key-value pair from the hash. Here's how it works:
Loop Iteration | key | value |
---|---|---|
1 | "name" |
"Alice" |
2 | "age" |
30 |
3 | "city" |
"Paris" |
Ruby each Loop
The each
loop is another way to iterate over collections. It is preferred by Ruby developers over the for loop due to its readability. Its syntax is:
collection.each do |item|
# Code using item
end
Here,
collection
- A collection of values like arrays or hashes.item
- A placeholder that takes the value of each element in thecollection
during each iteration.
Example 4: Ruby each Loop with Range
(4..6).each do |num|
puts num
end
Output
4 5 6
Here, the each
loop iterates over the range 4..6
. As a result, the loop runs three times over the numbers 4, 5, and 6.
In each iteration of the loop, the variable num
takes values from 4 to 6, which is then printed to the screen. Here's how it works:
Loop Iteration | Value of num |
---|---|
First | 4 |
Second | 5 |
Third | 6 |
Example 5: Ruby each Loop with Array
people = ["Bob", "Alex", "Sharon", "Cassie"]
people.each do |person|
puts person
end
Output
Bob Alex Sharon Cassie
Here, the each
loop runs once for each item in the people
array.
In each iteration, the person
variable takes a single element from the people
array, which is similar to how our for
loop example works:
Loop Iteration | Value of person |
---|---|
1 | "Bob" |
2 | "Alex" |
3 | "Sharon" |
4 | "Cassie" |
Example 6: Ruby each Loop with Hash
# Create a hash named 'person'
# "name", "age", and "city" are keys
# "Alice", 30, and "Paris" are the corresponding values
person = { "name" => "Alice", "age" => 30, "city" => "Paris" }
person.each do |key, value|
puts "#{key}: #{value}"
end
Output
name: Alice age: 30 city: Paris
Here, the each
loop runs once for each item in the person
hash.
In each iteration, the key
and value
variables of the loop take a key-value pair from the hash. Here's how it works:
Loop Iteration | key | value |
---|---|---|
1 | "name" |
"Alice" |
2 | "age" |
30 |
3 | "city" |
"Paris" |
Frequently Asked Questions
In Ruby, the one-line syntax for the each
loop uses curly braces {}
instead of do...end
:
collection.each { |item| # code using item }
Example
# With range
(1..3).each { |i| puts i }
# With array
[4, 5, 6].each { |i| puts i }
my_hash = { "name" => "Revan", "age" => 40 }
# With hash
my_hash.each { |key, value| puts "#{key}: #{value}" }
Output
1 2 3 4 5 6 name: Revan age: 40
In Ruby, the for
loop is internally built on top of the each
method. So when you write a for
loop, Ruby is actually calling each
behind the scenes.
As a result, these two loops are almost identical. However, the two loops differ when it comes to variable scope:
- The
for
loop variable belongs to the same scope as the one in which the loop is written. In other words, you can use the variable outside the loop. - The
each
loop variable only belongs inside the loop, and cannot be used outside it.
As mentioned in the previous FAQ, you can use for
loop variables outside the loop, but you can't do the same with the each
loop.
Example: Scope of the for Loop
for i in 1..3
puts "i = #{i}"
end
# Valid: Using i outside the for loop
puts "i = #{i}"
Output
i = 1 i = 2 i = 3 i = 3
Here, we can access the i
variable outside the for
loop because the scope of the for
loop is the same as the one in which the loop is written.
Example: Scope of the each Loop
(1..3).each do |i|
puts "i = #{i}"
end
# Invalid: Using i outside the each loop
puts "i = #{i}"
Output
i = 1 i = 2 i = 3 main.rb:6:in '<main>': undefined local variable or method 'i' for main (NameError)
As you can see, we get a NameError
when trying to access the i
variable outside the each
loop.
That's because the i
variable is local to the block given to the each
method. It is not accessible outside the block.
In other words, the each
loop has its own scope (unlike the for
loop).