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, some JS stuff and more...

Github:
/danielmoralesp
Twitter:
@danielmpbp

2024-10-08

Ruby Each Loop

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

Loops allows 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? Well, with the "each" loop we can go over a list of things and work with each individual element which is something really useful. So we’re going to 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 and then we iterate through it and we work with each individual 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

Array is a data type in Ruby. We've learnt in a previous post about data types like: Numbers, Strings and Booleans. 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 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. In the second array we saved an integer, a string and finally a Boolean. As you can see we can have equal 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. Actually 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 having to 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 day 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 seems little awkward at the beginning, but let me explain what it means:


  • * In first line of code we have an array of numbers: [1, 2, 3, 4]
  • * Then we call immediately the ruby method “.each
  • * We finish the first line of code with the start of a Ruby block with the keyword “do
  • * Inside the body of the block 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 a similar behavior? Think a bit about it. The answer is because 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 real 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 as before and also we keep the “.each” method next to the array and the “do” keyword after that. But we’re seeing other weird syntax: |element|
  • * At the end of the first line we’ve 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 named as you want, and normally you’ll find names like “e”, “i” or “index”. It doesn't matter the name, what it 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 that the target of the “each” loop is to go over a list of things & work with each individual element. Let's modify a bit more the body of the ruby block 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 element of the array, so we’re doing an operation to have another result. Is fair to say that the array is not modified at this point (we should need to do other modifications to the body of the block) but by now this is enough to understand the "Each" loop. 

Obviously we can refactor a bit this code to use a variable instead 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 at the beginning of this blog post we talked about the keywords do/end. Now Ruby provides an alternative way to build these blocks. This alternative way is useful when we have a small body to be executed inside the block. In the last example we saw that the only thing we want to do inside the block is to print each element, so we can easily 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 in just one line of code. Remember that this makes sense when the body of the block is small, because if we have more lines of code inside it, it could be turned unreadable. Always choose reliability over other things.


With this we have enough basic knowledge to work with the “Each” method in Ruby

Hope you learned a lot!

Thanks for reading 
DanielM