Ruby Monstas


Loops for Arrays

Why loops?

Assume we have an array with names, and we want to greet every name.

friends = ['Alice', 'Betty', 'Chris']

How could we do that?

Why loops? Cont. I

We could do this:

puts "Hi #{friends[0]}"    # Hi Alice
puts "Hi #{friends[1]}"    # Hi Betty
puts "Hi #{friends[2]}"    # Hi Chris
🤔 This is suboptimal.
If we have 100 friends, we don't want to write puts "Hi #{...}" so many times.

Why loops? Cont. II

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.

Why loops? Cont. III

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.

Breaking news!

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

Loops to the rescue

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!

Have a break, have a ...

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

One more thing

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 .

Solved: Looping through an array

friends = ['Alice', 'Betty', 'Chris']

counter = 0

loop do
  if counter < friends.count
    puts "Hi #{friends[counter]}"
    counter = counter + 1
  else
    break
  end
end

Theory: Check ☑️

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. II

It'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

Another example

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

Last example

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?