
Welcome to the ninth installment of Enumerating Enumerable, the series of articles where I attempt to do a better job at documenting Ruby’s Enumerable
module than Ruby-Doc.org does.
I’m going through the Enumerable
‘s methods in alphabetical order, and we’ve reached the methods that are variations on each
In this article, I’m going to cover each_cons
, which got introduced in Ruby 1.9.
If you missed any of the earlier articles, I’ve listed them all below:
- all?
- any?
- collect / map
- count
- cycle
- detect / find
- drop
- drop_while
Enumerable#each_cons Quick Summary

In the simplest possible terms |
Think of each_cons as an each that takes a number n and spits out n elements at a time. |
Ruby version |
1.9 only |
Expects |
A number n describing the number of elements to be fed to the block. |
Returns |
nil if used with a block
- An
Enumerator object that outputs n-sized consecutive array slices of the collection if used without a block.
|
RubyDoc.org’s entry |
Enumerable#each+cons |
Enumerable#each_cons and Arrays
When used on an array and given a block and a number n as an argument, each_cons
is like an each
that goes through each element in the array and outputs an n-sized array slice of the original array starting at the current element.
each_cons
is one of those methods that’s really tough to describe. This is one of those cases where a demonstrating trumps describing…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
justice_league = ["Aquaman", "Batman", "Black Canary", \ "Flash", "Green Arrow", "Green Lantern", \ "Martian Manhunter", "Superman", \ "Vixen", "Wonder Woman"] => justice_league = ["Aquaman", "Batman", "Black Canary", "Flash", "Green Arrow", "Green Lantern", "Martian Manhunter", "Superman", "Vixen", "Wonder Woman"] justice_league.each_cons(3) {|team| p team} => ["Aquaman", "Batman", "Black Canary"] ["Batman", "Black Canary", "Flash"] ["Black Canary", "Flash", "Green Arrow"] ["Flash", "Green Arrow", "Green Lantern"] ["Green Arrow", "Green Lantern", "Martian Manhunter"] ["Green Lantern", "Martian Manhunter", "Superman"] ["Martian Manhunter", "Superman", "Vixen"] ["Superman", "Vixen", "Wonder Woman"] => nil |
Note that in this case, each_cons
returns nil
.
each_cons
can also be used without providing a block. In this case, you’re using it to create an Enumerator
object that you can then use to spit out array slices when you call its next
method:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
# Let's create an enumerator that we can use to give us three-person # superhero teams teams_of_3 = justice_league.each_cons(3) => #<enumerable::Enumerator:0x007f8f83ecc538> # Let's get the first team of 3 teams_of_3.next => ["Aquaman", "Batman", "Black Canary"] # Now the next one... teams_of_3.next => ["Batman", "Black Canary", "Flash"] teams_of_3.next => ["Black Canary", "Flash", "Green Arrow"] teams_of_3.next => ["Flash", "Green Arrow", "Green Lantern"] # Let's go back to the first team of 3 teams_of_3.rewind => #<enumerable::Enumerator:0x007f8f83ecc538> teams_of_3.next => ["Aquaman", "Batman", "Black Canary"] |
Enumerable#each_cons and Hashes
When used on a hash and given a block and a number n as an argument, each_cons
is like an each
that goes through each element in the array and outputs an n-sized array slice of the hash starting at the current element. Note that in the process, hash elements are converted into two-element arrays where the first element contains the key and the second element contains the corresponding value.
Again, examples speak louder than descriptions:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
enterprise_crew = {:captain => "Picard", :first_officer => "Riker", :science_officer => "Data", :tactical_officer => "Worf", :chief_engineer => "LaForge", :chief_medical_officer => "Crusher", :ships_counselor => "Troi", :annoying_ensign => "Crusher", :attractive_ensign => "Ro", :expendable_crew_member => "Smith"} => {:captain=>"Picard", :first_officer=>"Riker", :science_officer=>"Data", :tact ical_officer=>"Worf", :chief_engineer=>"LaForge", :chief_medical_officer=>"Crush er", :ships_counselor=>"Troi", :annoying_ensign=>"Crusher", :attractive_ensign=> "Ro", :expendable_crew_member=>"Smith"} enterprise_crew.each_cons(3) {|team| p team} => [[:captain, "Picard"], [:first_officer, "Riker"], [:science_officer, "Data"]] [[:first_officer, "Riker"], [:science_officer, "Data"], [:tactical_officer, "Worf"]] [[:science_officer, "Data"], [:tactical_officer, "Worf"], [:chief_engineer, "LaForge"]] [[:tactical_officer, "Worf"], [:chief_engineer, "LaForge"], [:chief_medical_officer, "Crusher"]] [[:chief_engineer, "LaForge"], [:chief_medical_officer, "Crusher"], [:ships_counselor, "Troi"]] [[:chief_medical_officer, "Crusher"], [:ships_counselor, "Troi"], [:annoying_ensign, "Crusher"]] [[:ships_counselor, "Troi"], [:annoying_ensign, "Crusher"], [:attractive_ensign, "Ro"]] [[:annoying_ensign, "Crusher"], [:attractive_ensign, "Ro"], [:expendable_crew_member, "Smith"]] => nil |
As with arrays, each_cons
, when used on a hash, returns nil
.
Again, as with arrays, each_cons
can also be used without providing a block to create an Enumerator
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
# Starfleet has decided to let the ship's computer determine # the away teams, which are groups of 3 away_teams_of_3 = enterprise_crew.each_cons(3) => #<enumerable::Enumerator:0x007f8f83ee82b0> # Okay, who's the first away team? away_teams_of_3.next => [[:captain, "Picard"], [:first_officer, "Riker"], [:science_officer, "Data"]] # Let's get the next one away_teams_of_3.next => [[:first_officer, "Riker"], [:science_officer, "Data"], [:tactical_officer, "Worf"]] away_teams_of_3.next => [[:science_officer, "Data"], [:tactical_officer, "Worf"], [:chief_engineer, "LaForge"]] # Let's go back to the first away team away_teams_of_3.rewind => #<enumerable::Enumerator:0x007f8f83ee82b0> away_teams_of_3.next => [[:captain, "Picard"], [:first_officer, "Riker"], [:science_officer, "Data"]] |