What is Enumerable?

Enumerable is a collection of iteration methods, a Ruby module, and a big part of what makes Ruby a great programming language.

Enumerable includes helpful methods like:

map

select

inject

Enumerable methods work by giving them a block.

In that block you tell them what you want to do with every element.

For example:

[1,2,3].map { |n| n * 2 }

Gives you a new array where every number has been doubled.

Exactly what happens depends on what method you use, map helps you transform all the values, select lets you filter a list & inject can be used to add up all the values inside an array.

There are over 20 Ruby Enumerable methods.

Let’s study one in detail.

The Each_Cons Method

My new favorite Enumerable method is each_cons !

Here’s why:

This method is really useful, you can use it to find n-grams or to check if a sequence of numbers is contiguous when combined with all? , another Enumerable method.

each_cons gives you sub-arrays of size n , so if you have [1,2,3] , then each_cons(2) will give you [[1,2], [2,3]] .

Let’s see an example:

numbers = [3,5,4,2] numbers.sort.each_cons(2).all? { |x,y| x == y - 1 }

This code starts by sorting the numbers, then calling each_cons(2) , which returns an Enumerator object, and then it calls the all? method to check if all the elements match the condition.

Here is another example, where I use each_cons to check if a character is surrounded by the same character, like this: xyx .

str = 'abcxyx' str.chars.each_cons(3).any? { |a,b,c| a == c }

There is more!

If you wanted to know how many times this pattern occurs, instead of getting a true / false result, you can just change any? to count .

What I find even more fascinating is the implementation for the each_cons method.

array = [] each do |element| array << element array.shift if array.size > n yield array.dup if array.size == n end

Note: This comes from the Rubinius implementation of Enumerable . You can find the original source code here.

The implementation starts with an empty Ruby array, then it iterates through the elements using each .

Everything is pretty standard until here. But then it adds the element to the array and it trims the array (using Array#shift) if the size is bigger than what we want.

The size is the argument to each_cons .

Then it yields a dup of the array if the array has the requested size.

I think this is genius, because it keeps a ‘sliding window’ sort of effect into our enumerable object, instead of having to mess around with array indexes.

More Fascinating Methods

Method Description count Exactly what the name says, count things that evaluate to true inside a block group_by Group enumerable elements by the block return value. Returns a hash partition Partition into two groups. Returns a two-dimensional array any? Returns true if the block returns true for ANY elements yielded to it all? Returns true if the block returns true for ALL elements yielded to it none? Opposite of all? cycle(n) Repeat ALL the elements n times, so if you do [1,2].cycle(2) you would have [1,2,1,2] find Like select , but it returns the first thing it finds inject Accumulates the result of the previous block value & passes it into the next one. Useful for adding up totals zip Glues together two enumerable objects, so you can work with them in parallel. Useful for comparing elements & for generating hashes map Transforms every element of the enumerable object & returns the new version as an array

Wrapping Up

As you have seen, Enumerable is a module that is worth mastering, so hop over to the documentation and see what it can do for you!

Don’t forget to share & subscribe to my newsletter in the form below if you enjoyed this article. It would help me a lot! 🙂