Loops for Arrays
Assume we have an array with names, and we want to greet every name.
friends = ['Alice', 'Betty', 'Chris']
How could we do that?
We could do this:
puts "Hi #{friends[0]}" # Hi Alice
puts "Hi #{friends[1]}" # Hi Betty
puts "Hi #{friends[2]}" # Hi Chris
puts "Hi #{...}"
so many times.
Let's look at the code.
Only one thing changes in each line:
puts "Hi #{friends[0]}"
puts "Hi #{friends[1]}"
puts "Hi #{friends[2]}"
We could use a counter
and increase the number before we greet the next person.
counter = 0
puts "Hi #{friends[counter]}" # counter is 0
counter = counter + 1
puts "Hi #{friends[counter]}" # counter is 1
counter = counter + 1
puts "Hi #{friends[counter]}" # counter is 2
counter = counter + 1
🤦♀️ We made it worse.
For every additional friend,
we have to repeat even two lines.
We did not make it worse!
Except the first line, everything repeats:
That's an opportunity!
counter = 0
puts "Hi #{friends[counter]}" # Instruction 1
counter = counter + 1 # Instruction 2
puts "Hi #{friends[counter]}" # Instruction 1
counter = counter + 1 # Instruction 2
puts "Hi #{friends[counter]}" # Instruction 1
counter = counter + 1 # Instruction 2
The shown pattern enables us to use a loop.
And it's super simple:
counter = 0
loop do
puts "Hi #{friends[counter]}" # Instruction 1
counter = counter + 1 # Instruction 2
end
🤨 ...something's wrong though!
The example before would run forever.
We need to stop it after 3 iterations.
Easy. Let's check the counter
's value in each iteration
counter = 0
loop do
if counter < 3 # 0, 1 and 2 pass. 3 doesn't.
puts "Hi #{friends[counter]}"
counter = counter + 1
else
break # this exits the loops
end
end
The abort condition if counter < 3
needs improvement.
3
should be a dynamic value: The number of elements in the friends
array!
We can replace it with friends.count
.
friends = ['Alice', 'Betty', 'Chris']
counter = 0
loop do
if counter < friends.count
puts "Hi #{friends[counter]}"
counter = counter + 1
else
break
end
end
This is how we could iterate through an array, but...
...Ruby offers an alternative way to do the same,
please welcome:
.each
.each
This does the same as loop
with a counter
,
but it hides everything in the background.
friends = ['Alice', 'Betty', 'Chris']
friends.each do |friend_name|
puts "Hi #{friend_name}"
end
.each
Cont. IIIt's a loop
.
There's no (visible) counter
.
There's no (visible) abortion criteria.
The variable between the vertical bars ||
automatically holds the value
friends = ['Alice', 'Betty', 'Chris']
friends.each do |friend_name|
puts "Hi #{friend_name}"
end
You can use .each
on an array of numbers too.
Note: We define the variable name between ||
. In the example we name it i
.
numbers = [3, 6, 9]
numbers.each do |i|
squared = i * i
puts "#{i} * #{i} is #{squared}"
end
# 3 * 3 is 9
# 6 * 6 is 36
# 9 * 9 is 81
Here we name the variable thing
, we could have named it anything else.
animals = ['Horse', 'Penguin', 'Squirrel']
animals.each do |thing|
puts "'#{thing}' reversed is '#{thing.reverse}'"
end
# 'Horse' reversed is 'esroH'
# 'Penguin' reversed is 'niugneP'
# 'Squirrel' reversed is 'lerriuqS'
What questions do you have?