Share this post!

My New Favorite Enumerable Method

Enumerable is an amazing module, and it’s a big part of what makes Ruby a great programming language.

Ruby’s Enumerable gives you all sorts of cool methods like:

  • map
  • select
  • inject

But my new favorite 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.

enumerable each_cons

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

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! 🙂

Serguei Cambour (@belgoros) says a couple of years ago

Really helpful article, thank you so much for sharing it, Jesus!!!

    Jesus Castello says a couple of years ago

    Thank you for reading 🙂

ttw (@ttwo32) says a couple of years ago

Thank you for sharing article. I will read the documentation.

    Jesus Castello says a couple of years ago

    There are lots of interesting methods there. Check out the partition method 🙂

Comments are closed