# 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 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,

`.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?