Iterator Methods in Ruby

Michael Werling
4 min readMar 29, 2021

As I mentioned in my original post about my first project, one of the hardest aspects to grasp was how to take a collection of data and access it in my program. Thankfully, the Ruby program language comes with built in methods called iterators which allow a program to iterate through an entire collection and do something to each element contained within.

I wanted to take some time to highlight a few of these iterator methods today and explain some similarities and differences between how they are used in common programs.

How do Iterator Methods Work?

Each of the methods that I will discuss below are used to do something to an entire collection of data. This data could be collected in a hash or an array, but each instance in this collection will have a certain task done to them. This process will continue over and over until all instance have been completed. The format for these methods is seen below.

collection.method do |instance_name|
perform something on each instance using "instance_name"
end

Immediately after an iterator method is called the program must open a block. A block is a bunch of code set between do/end keywords that you can pass a method to like you can pass an argument to a method.

You can see from this format that you must create a variable name to describe each instance in the collection then call additional code using that variable name. This variable name is put in between | | pipes and is created after a new block is formed.

Alternatively, a block can also be put inside of { } brackets. If you wanted to use this formatting for an iterator method, it would look like this.

collection.method { |instance_name| perform something on each instance using "instance_name"}

Each Method

The first instance method that I want to highlight is called the .each method. This method goes through each iteration and returns each value that is contained in the original collection.

school_colors = ["Brown", "Black", "Green", "Blue]
school_colors.each do |color|
puts "School Color #{color} is #{color.length} letters long."
end

As you can see in the example above, this code will simply take each of the values contained in the school_colors array and place them into the sentence output using basic string interpolation #{} . The final output for the code above can be seen below.

School Color Brown is 5 letters long.
School Color Black is 5 letters long.
School Color Green is 5 letters long.
School Color Blue is 4 letters long.

It is important to note the the return value of the collection remains the exact same after you have performed this method. For example, the return value for the original collection on our example is still [“Brown”, "Black”, "Green”, "Blue”]

Map/Collect Method

The next method that I would like to highlight is the .map method. This method can also be called .collect, which will do the same thing in Ruby

Like the .each method outlined above, .map will go through and grab each instance in the collection, but this method actually has the ability to change the return value of the original collection after the code has been performed. Please see below an example for how this method works.

toppings = ["pickles", "mushrooms", "bacon"]toppings.map do |topping|
"I love #{topping} on my burgers"
end
Return Value:["I love pickles on my burgers",
"I love mushrooms on my burgers",
"I love bacon on my burgers"]

If we had used .each in this example, the method would have printed a list just like this; however, the return value from this method would still be the original array ( [“pickles”, "mushrooms”, "bacon”])

It is for this reason that I needed to use .map for my first project when I wanted to go in and physically remove data from the API that I wanted to use. If I had used .each, I would just be stuck with the same massive list of data each time I wanted something returned.

Select/Find_all

The third type of iterator that I want to discuss is the .select (or .select_all) method.

The select method can be performed on a collection so that the return value is an array of all of the instances in the collection that return true. This means that you are asking a question about each instance and, if that instance can answer yes to that question, it will be kept in the return value array.

[1,2,3,4,5].select do |number|
number.even?
end #=> [2,4]

The above example asks whether each instance is an even number. As you can see by the final return value, only 2 and 4 answer “yes” to this question.

It is important to know that if no element can answer true, an empty array is returned.

This type of iterator method is good for creating a list of elements that a user might be looking for rather than just giving one output from the collection.

Find/Detect

The final Ruby iterator method that I wanted to highlight in this post is called .find (or .detect).

This iterator method is very similar to the .select method outlined above. Where .select will return all elements from the collection that cause the block to evaluate true, .find will only return the first element that makes the block true.

[1,2,3].detect{|i| i.odd?} #=> 1[1,2,3].find{|i| i.odd?} #=> 1

As you can see in the example above , 1 and 3 are both odd numbers and should evaluate to true, but because 1 is first in the array, it alone is returned.

[1,3,5].detect{|i| i.even?} #=> nil

Notice that .find will always return a single object, where .select will always return an array. Additionally, if .detect cannot find any instances that return true, the return value will be nil.

For more information on how I used the .find iterator in my first project, please read my blog post “Follow up to my first CLI application”.

--

--