How to Use the Each Method in Ruby

How to Use the Each Method in Ruby

When it comes to doing the same thing over and over again, Ruby has a few methods you can choose from. But in this article, we’re going to look at the each method, how to use it, and what you can do with it.

When you think about Ruby, you think OOP. And that’s ok. Ruby is an Object-Oriented Programming language after all.

But, Ruby being a beautiful beast of a programming language, it also lets you combine OOP with functional programming. Don’t worry; you’ve probably done this without realizing it.

Functional programming lets you describe what you want to do, as opposed to how you want it done. An example of what would be “Give me all the even numbers in this list.”. You don’t really care about how it’s doing it, you’re telling it what you want.

[1,2,3].select(&:even?)

Forget about the syntax and how select works right now, and just think about how expressive that operation is.

How does each work in Ruby?

each is just another method on an object. That means that if you want to iterate over an array with each, you’re calling the each method on that array object.

It takes a list as it’s first argument and a block as the second argument. For every element in the list, it runs the block passing it the current element as a parameter.

You should use each when you want iteration but don’t care about what it returns.

But let’s see an example.

Looping through an array with each

[1, 2, 3].each { |n| puts "Current number is: #{n}" }
Current number is: 1
Current number is: 2
Current number is: 3

For every element in the array, each runs the block, passing it the element as an argument (n in the example above).

You don’t have to pass the block inline. A multiline block is recommended when you’ve got multiple lines in the block, or when the line is too long. It improves readability.

[1, 2, 3].each do |n|
  text = "Current number is: #{n}"
  puts text
end
Current number is: 1
Current number is: 2
Current number is: 3

Looping through a hash with each

It might sound surprising that you can actually iterate over a hash, but if you think about it, a hash is a list of key value pairs.

And the fact that the each method is just a method, on a hash object in this case, you can implement it to behave just like it does with an array object.

my_hash = {min: 2, max: 5}
my_hash.each { |key, value| puts "k: #{key}, v: #{value}" }
k: min, v: 2
k: max, v: 5

The difference is that in this example, the block receives two arguments. The first argument is a key, and the second one is the value.

each vs. each_pair when looping through a hash

Ruby calls an object that can be iterated over, an enumerable. And it provides an Enumerable module that you can use to make an object an enumerable.

There are a few methods you need to implement to become an enumerable, and one of those is the each method.

So because Hash is also an enumerable, it needs to implement the each method. But it also has a better named one, called each_pair.

Basically, they are just aliases for each other. They share the same code.

How do you set a starting offset

It’s sometimes useful to not start at the beginning of the list, but to skip a few items. So to set a different starting point for the loop, you can use a range.

my_list = [1, 2, 3, 4 ,5]
[3..-1].each { |i| puts i }
my_list[3..-1].each { |i| puts i }
4
5

Another way is to use drop. It’s part of the Enumerable module, so every enumerable object supports it. As the name suggests, drop(n) skips the first n elements and uses the rest for the loop.

[1, 2, 3, 4 ,5].drop(3).each { |i| puts i }
4
5

How to break out from the each block

There are cases in which you don’t want to continue running the loop if some condition has been met. In that case you can use the break keyword.

[1,2,3].each do |i|
  break if i == 3
  puts i
end
1
2

In this example, we check to see if the value of i is equal to 3. And if it is, we call break which stops everything and gets out of the loop.

For vs. each in Ruby

Those coming from an imperative language might be more familiar with the for loop. Let’s see how a for loop looks like.

# imperative for
for i in [1,2,3] do
  puts i
end

# functional each
[1,2,3].each { |i| puts i }

As you can imagine, the results are identical. So why would you then choose one over the other?

There is a scope difference. After the for loop runs, the iterator variable (i.e. i) still exists. That doesn’t happen with each, because each introduces a new lexical scope.

for i in [1,2,3] do
  puts i
end
puts i # => 3

[1,2,3].each { |n| puts n }
puts n # => NameError: undefined local variable or method `n'

And if you really need the iterator value where the loop exited, you can do it like this.

last_value = [1, 2, 3].each do |n|
  break n if n % 2 == 0
end

You should use each over for. It is more idiomatic, and faster than for.

Finding out current index in an each loop

It’s sometimes useful to know where you are in the list, so for that you need to have an index. While each doesn’t give you that, you can use each_with_index.

It takes two parameters. The first one is the element, and the second one is the index.

['a', 'b', 'c'].each_with_index { |el, i| puts i }
0
1
2

Is it possible to access the index in a Hash each loop?

You’ve seen how all enumerators have the same methods and such. So if Hash is an Enumerator, like Array is, then it should be possible to have that index on a hash too. Right? Right!

[1, 2, 3].each_with_index { |(k, v), i| puts i }
0
1
2

There you go. You now know how to use the each method.

If you liked this article, please take a moment and say thanks by sharing it on your favorite social media channel.