Now that we've talked about arrays, let's talk about looping.
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
andend
, 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{
andend
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.
countries
array with the each
methodcountry
. This way we can reference country
inside the blockcountry
is equal to "Nepal"
country
is equal to "America"
country
is equal to "Malaysia"
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
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.
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
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
Write a program the does the following:
The results should be case insensitive
"Pizza"
and "pizza"
should be counted as the same wordThe program should run like this:
This is a tricky problem! Good luck on this challenge!