10. Looping and Iterating

Now that we've talked about arrays, let's talk about looping.

each

numbers = [1,2,3,4,5]

Here we have a numbers array. We can iterate through each item in the array with the each method. Programmers will use the word iterate a lot - it means to go through each item one by one. Let's look at an example:

numbers.each do |i|
  puts i
end
1
2
3
4
5
=> [1, 2, 3, 4, 5]

As you can see, the program is going through each number in the numbers array, and printing it out. There's a few new things we have never seen before. First, let's look at the do and end.

The code that is inbetween do and end is called a block. A block is a piece of code that can be executed. In our example, our block consists of puts i.

Blocks

Blocks in Ruby are a set of instructions that are passed around your program.

Blocks are created either with do and end, or with {}s. For example, these two pieces of code do the same thing:

numbers.each do |i|
  puts i
end
numbers.each {|i| puts i}

At first, converting these two syntaxes can be confusing. An easy way to remember the syntax is to replace do with { and end with } and vice-versa.

The i inbetween the |s is a block argument. Block arguments are basically variables that can be used within the block. The arguments can be named anything. The | characters are called pipe characters, and the variable inbetween them are the block arguments.

|i| is called a block argument. The block argument acts exactly like a regular variable, except it is only valid within the block.

numbers.each do |i|
  # i works inside this block
  # Again, the block starts at 'do' and ends at 'end'
  puts i
end

# i doesn't work outside of the block
puts i
=> NameError: undefined local variable or method `i' for main:Object

Also, the block argument (the variable between the pipe characters) can be named anything:

numbers.each do |random_name|
  puts random_name
end

Even though we changed i to random_name, the result is still the same:

1
2
3
4
5
=> [1, 2, 3, 4, 5]

However, it is good practice to name variables in a way that it makes sense. In other words, instead of random_name, naming the variable something like i or n or number is more appropriate.

One of my teachers from college once said that naming variables is one of the hardest things about programming. I'm not sure if I completely agree, but it is true that naming variables is extremely important. To write good expressive code, it is important to name variables in a way that makes sense.

Let's take a look at this code once again:

numbers.each do |i|
  puts i
end

Here is how you should read the above code in English: For each item (i) in the numbers array, print out the item (i).

Inside the block, we can run any piece of code. Take a look at the following piece of code:

numbers.each do |i|
  puts i * 2
end

Result:

2
4
6
8
10
=> [1, 2, 3, 4, 5]

As you can see, the program printed out each number multiplied by 2.

Let's take a look at another example. First, let's declare an array and push in some strings:

countries = []
countries.push("Nepal")
countries.push("Japan")
countries.push("Malaysia")

To give you a refresher, the push array method pushes the element passed in as the parameter to the array.

Now let's iterate through each country:

countries.each do |country|
  puts "#{country} is awesome!"
end

Nepal is awesome!
Japan is awesome!
Malaysia is awesome!

Let's go over each step of this program.

while loop

Most languages have a while loop. While loops are pretty straightforward:

i = 0

while (i < 5) do
  puts i
  i += 1
end

Result:

0
1
2
3
4

While loops execute the code inbetween do and end until the condition (in this case i < 5) is false.

while (condition_is_true) do
  # execute code here
end

times loop

Ruby has another way to loop, which is the times loop.

10.times do |i|
  puts i
end

Result:

0
1
2
3
4
5
6
7
8
9
=> 10

As you can see, the placeholder variable i starts at 0 and increments each time it loops.

Another example:

5.times do
  puts "this is spam"
end

Result:

this is spam
this is spam
this is spam
this is spam
this is spam
=> 5

Again, the code inbetween do and end is executed.

upto loop

You can also loop using upto.

1.upto(10) do |n|
  puts n
end

Result:

1
2
3
4
5
6
7
8
9
10

downto loop

Similarly, there is a downto loop as well.

10.downto(0) do |n|
  puts n
end

Result:

10
9
8
7
6
5
4
3
2
1
0

Coding Challenge

Write a program the does the following:

The program should run like this:

image.png

This is a tricky problem! Good luck on this challenge!