An
Enumerator
is defined as a “class which allows both internal and external iteration.” It represent a series of objects, it can be lazily generated and it can be infinite. In contrast, the anEnumerable
is a module and it “provides collection classes with several traversal and searching methods, and with the ability to sort.”
In Ruby, enumerators are used quite frequently for their extensive abstraction of iteration functionality. When we call the Array#each
method, we can focus on dealing with the individual Array
items rather than having to worry about how to retrieve each item one by one. When we need to find a subset of items from a Hash
, we can use #select
with a code block to decide which item we want in the result, without necessarily knowing how the Hash
is traversed.
All this power comes from the Enumerable
module, and it is inlucded by many of the common Object types such as Array
, Hash
, Range
, and Set
. When first learning Ruby, #each
and #collect
quickly become an often-used tool we use for iterating over data. Most functionality can be accomplished by their use, however, there are many more advanced iterators available with very specific funtionality, but unless we constantly skim over the Ruby documentation, we may not know about them. I’d like to introduce (or re-introduce for some of you) some of my favorites.
#count
Alright, alright. You may use #count
on a daily basis, but did you know that you can specify a parameter to the method call? It will return the number of occurrances of that particular value.
1 2 3 |
|
If you though that was cool, then hold on to your pants. When you add a block that evaluates a condition for each item in the collection, you can add logic regarding which items you want to count. If the block return true
the item gets counted.
1 2 |
|
#lazy
We all like to be lazy sometimes. Starting in Ruby 2.0, we can now let Enumerable
objects be lazy too. All this means is that the result of the enumerable function will not get evaluated until you tell it to.
1 2 3 4 5 6 7 |
|
The behavior in this example doesn’t really show the full potential of #lazy
. Imagine that you have an operation that you want to apply to a collection, however, the contents of the given collection are dynamically changing. Using #lazy
keeps the enumerator updated with the latest state of the collection.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|