Back-end Engineering Articles

I write and talk about backend stuff like Ruby, Ruby On Rails, Databases, Testing, Architecture / Infrastructure / System Design, Cloud, DevOps, Backgroud Jobs, and more...

Twitter:
@daniel_moralesp

2019-05-17

Ruby Each Loop

In a previous post called Ruby Times Loop and While Loop, we've been talking extensively about Loops, and we said that:

Loops allow you to:
* Go over a list of things & work with each individual element
* Repeat something a set number of times
* Keep a program running until the user wants to stop it

The "Each" loop is one of the most widely used loops inside the Ruby programming language. Why is this? With the "each" Loop, we can go over a list of things and work with each element, which is really useful. So we will use it prominently to do that kind of job. This is particularly true when we start to work with databases.

With databases, we retrieve data, then iterate through it, and work with each element, doing things like updating it or just printing it to the user. It's fair enough to say that we can do this task with any other Ruby Loops; however, "Each" Loop is the standard gold for Ruby to do that kind of job. But before we go further, let's see two important concepts here: Ruby Blocks and Arrays.

Ruby Blocks - Part 1

Blocks are enclosed in a do-end statement. So far, we've seen some ruby blocks in the Times Loop and While Loop post. Let's see it again more in-depth.

10.times do
  # do something 10 times
end

We can see the block starting with the "do" keyword and ending with the "end" keyword. Everything inside the block is called the "body." The body is what we need to execute once we're inside the block. It's actually that simple.

Arrays

The array is a data type in Ruby. We've learned about numbers, strings, and Booleans data types in a previous post. In the next blog post, we'll be seeing Ruby arrays deeply, but for now, we need just to understand that an array is a container of other ruby data type elements. The syntax starts with an open bracket "["then inside of it we put the elements separated by a comma and finally closing the array with a closed bracket "]." Examples:

2.6.8 :004 > [1, 2, 3, 4]
 => [1, 2, 3, 4] 
2.6.8 :005 > [1, "hello", true]
 => [1, "hello", true]


In the first array, we containerize just integer elements. We saved an integer, a string, and a Boolean in the second array. As you can see, we can have similar or different types of elements inside the array. But why do we need to know about arrays here? Because the "Each" Loop can iterate over an array and then work with each individual element. You can see the "each" word in the last definition because that's the intent of the "each" Loop, do something on each element.


Each Loop

The Ruby method "Each" allows you to go over a list of items without having to keep track of the number of iterations or increase some kind of counter. It's the Ruby way of doing "repeat until done." Before you can use each, you need a collection of items like an array, a range, or a hash. Later we'll be learning about the other data types (range and hash); for now, we'll be doing "each" statements with array data types and using the Ruby blocks. 


2.6.8 :001 > [1, 2, 3, 4].each do
2.6.8 :002 >     puts "h"
2.6.8 :003?>   end
h
h
h
h
 => [1, 2, 3, 4] 


This code can seem a little awkward at the beginning, but let me explain what it means:

  • * In the first line of code, we have an array of numbers: [1, 2, 3, 4]
  • * Then we call the ruby method immediately ".each"
  • * We finish the first line of code with the start of a Ruby block with the keyword "do."
  • * Inside the block's body, we want to print the string "h."
  • * Then, we close the ruby block with the keyword "end."
  • * The program immediately prints 4 times the character "h."

This is pretty similar to the ".times" ruby method that we saw in our last blog post. But why does "each" Loop have identical behavior? Think a bit about it. The answer is that we are doing something a certain amount of times given the number of elements of the array. If you count the number of elements inside the array, they sum up 4 elements. For that reason, Ruby printed out 4 "h" s. Then in this particular case, it is better to use the ".times" method. Now let's do a similar example with the actual utility of the ".each" method.


2.6.8 :010 > [1, 2, 3, 4].each do |element|
2.6.8 :011 >     puts element
2.6.8 :012?>   end
1
2
3
4
 => [1, 2, 3, 4]



Can you see the difference? 

This is quite different; let me explain each line of code again.

  • * In the first line, we keep the same ruby array, and also we keep the ".each" method next to the array and the "do" keyword after that. But we're seeing another weird syntax: |element|
  • * At the end of the first line, we have this "|element|." This means that Ruby will "iterate" inside the array data type, and each element will be saved in the variable named "element." This variable can be called as you want, and usually, you'll find names like "e," "i," or "index." It doesn't matter the title; what matters is what they store. They store each element of the array
  • * Inside the body of the ruby code, we printed out the variable named "element," which contains each element of the array
  • * And finally, we close the Ruby block with the keyword "end."


This makes more sense for what we're trying to do. Remember, the target of the "each" Loop is to go over a list of things & work with each individual element. Let's modify the ruby block's body a bit more to see its powers.


2.6.8 :013 > [1, 2, 3, 4].each do |element|
2.6.8 :014 >     puts element * 10
2.6.8 :015?>   end
10
20
30
40
 => [1, 2, 3, 4] 




Here is where we see the real power of "Each" Loop in Ruby. We're doing an operation (multiplying by 10) for each array element, so we're doing a procedure to have another result. It is fair to say that the array is not modified at this point (we should need to do other modifications to the block's body), but by now, this is enough to understand the "Each" Loop. 

Obviously, we can refactor this code to use a variable instead of iterating directly on the array.

2.6.8 :001 > array = [1, 2, 3, 4]
 => [1, 2, 3, 4] 
2.6.8 :002 > array.each do |element|
2.6.8 :003 >     puts element * 10
2.6.8 :004?>   end
10
20
30
40
 => [1, 2, 3, 4] 


Can you see the difference? I hope so!


Ruby Blocks - Part 2

In Ruby Blocks - Part 1, we talked about the keywords do/end at the beginning of this blog post. Now Ruby provides an alternative way to build these blocks. This alternative is practical when we have a small body inside the block. In the last example, we saw that the only thing we want to do inside the block is print each element to quickly use this other alternative. This is the syntax.


2.6.8 :005 > array = [1, 2, 3, 4]
 => [1, 2, 3, 4] 
2.6.8 :006 > array.each { |element| puts element * 10 }
10
20
30
40
 => [1, 2, 3, 4] 



Again it's a bit weird the way this line of code looks. Let me explain

  • * We've created the array variable with the correspondent elements: [1, 2, 3, 4]
  • * Then we called the ".each" method
  • * After that is what is different in comparison with the last code. We have and open "{"and close brackets "}" (instead of do/end keywords), and inside them, we have the same "|element|" variable that represents each internal array value, and after that, we have the "puts" keyword who prints the element multiplied by 10

  • Everything is just one line of code. Remember that this makes sense when the block's body is small because if we have more lines of code inside it, it could be turned unreadable. Always choose readability over other things.

We have enough basic knowledge to work with Ruby's "Each" method.

Hope you learned a lot!

Thanks for reading 
Daniel Morales.