enumerable

Enumerating Enumerable: Enumerable#each_with_index

by Joey deVilla on August 1, 2008

Enumerating Enumerable

Here’s number 11 in the Enumerating Enumerable series, in which I’m trying to outdo RubyDoc.org in their documentation of Ruby’s key Enumerable module. In this article, I cover the each_with_index method.

In case you missed the earlier articles, they’re listed and linked below:

  1. all?
  2. any?
  3. collect / map
  4. count
  5. cycle
  6. detect / find
  7. drop
  8. drop_while
  9. each_cons
  10. each_slice

Enumerable#each_with_index Quick Summary

Graphic representation of the \"each_with_index\" method in Ruby\'s \"Enumerable\" module

In the simplest possible terms Think of each_with_index as a version of each that includes an extra piece of information: a number representing the current iteration’s element’s position in the collection.
Ruby version 1.8 and 1.9
Expects An optional block to receive the values from each iteration.
Returns
  • The original collection, if used with a block.
  • An Enumerator object that outputs the collection’s items and indexes, if used without a block.
RubyDoc.org’s entry Enumerable#each_with_index

Enumerable#each_with_index and Arrays

When used with on an array and given a block, each_with_index iterates through the array, passing each item in the array and the number representing its order in the array to the block. Once again, I’ll use the “Justice League” example:

Note that unlike the each_cons and each_slice, each_with_index doesn’t return nil, but the original array, just like each does. each_cons and each_slice are newer methods that were introduced in Ruby 1.9; perhaps Matz and company decided that it made more sense for “each” methods to return nil from now on. each and each_with_index have return the original array as they always have, since making changes to these methods might break a lot of existing Ruby code. Hooray for those little inconsistencies that creep into every programming language!

Enumerable#each_with_index and Hashes

When used with on a hash and given a block, each_with_index iterates through the hash, converting each item in the hash into a two-element array (where the first element is the key and the second element is the corresponding value), and then passing that array and the number representing its order in the original array to the block. Once again, I’ll use the “Enterprise Crew” example:

Enumerable#each_with_index Oddities

Blocks with a Single Parameter

What happens if you use each_with_index with a block that has only one parameter? You’d think that the block would accept the item and index passed to it as a two-element array, with the item as the first element and the corresponding index as the second element, but that’s not the case:

When each_with_index passes an item and its index to a block that takes only one parameter, the item goes into the paramter, and the index is discarded. Simply put, in this case, each_with_index behaves just like each.

Without a Block

What happens if you use each_with_index without a block to create an Enumerator object that spits out the next item when its next method is called? This:

Note that calling next only yields the next item in the collection; the index information is lost. In this case, each_with_index behaves just like each.

{ 0 comments }

Enumerating Enumerable: Enumerable#each_slice

by Joey deVilla on July 29, 2008

Enumerating Enumerable

Ten installments already? That’s right, this is the tenth Enumerating Enumerable article. As I’m fond of repeating, this is my little contribution to the Ruby community: a series of articles where I attempt to do a better job at documenting Ruby’s Enumerable module than Ruby-Doc.org does, with pretty pictures and more in-depth examples!

In this article, I’m going to cover each_slice, which got introduced in Ruby 1.9.

If you missed any of the earlier articles, I’ve listed them all below:

  1. all?
  2. any?
  3. collect / map
  4. count
  5. cycle
  6. detect / find
  7. drop
  8. drop_while
  9. each_cons

Enumerable#each_slice Quick Summary

Graphic representation of the "each_slice" method in Ruby's "Enumerable" module

In the simplest possible terms Given a number n, split the array into n-element slices (if the number of elements in the array isn’t evenly divisible by n, just put the remaining elements in the last slice), then iterate through those slices.
Ruby version 1.9 only
Expects
  • A number n describing the size of the iteration slice.
  • An optional block to receive the values from each iteration.
Returns
  • nil, if used with a block.
  • An Enumerator object that outputs n-sized slices of the collection, if used without a block.
RubyDoc.org’s entry Enumerable#each_slice

Enumerable#each_slice and Arrays

When used on an array with a block, each_slice takes a numeric argument n and splits the array into slices of length n (if the number of elements in the array isn’t evenly divisible by n, the remaining elements are put into the last slice). each_slice then iterates through the set of slices, passing each slice to the block. After the final iteration, each_slice returns nil.

Since this is yet another case when an showing an example makes things very clear, I’ll do just that, using the same example data I used in the article on each_cons:

When used on an array without a block, each_slice takes a numeric argument n and returns an Enumerator that outputs slices of the array when its next method is called. Here’s an example:

Enumerable#each_slice and Hashes

When used on an hash with a block, each_slice takes a numeric argument n and splits the hash into arrays of length n (if the number of elements in the array isn’t evenly divisible by n, the remaining elements are put into the last slice). Within these arrays, each hash element is represented as a two-element array, with the first element being the key and the second element being the corresponding value.

each_slice then iterates through the set of arrays, passing each array to the block. After the final iteration, each_slice returns nil.

Here’s an example, using the same example data I used in the article on each_cons:

When used on a hash without a block, each_slice takes a numeric argument n and returns an Enumerator that outputs arrays when its next method is called. Here’s an example:

{ 0 comments }

Enumerating Enumerable: Enumerable#each_cons

by Joey deVilla on July 28, 2008

Enumerating Enumerable

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:

  1. all?
  2. any?
  3. collect / map
  4. count
  5. cycle
  6. detect / find
  7. drop
  8. drop_while

Enumerable#each_cons Quick Summary

Graphic representation of the \"each_cons\" method in Ruby\'s \"Enumerable\" module

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…

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:

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:

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:

{ 0 comments }

Enumerating Enumerable: Enumerable#drop_while

by Joey deVilla on July 25, 2008

After the wackiness of the past couple of weeks — some travel to see family, followed by a busy week of tech events including DemoCamp 18, Damian Conway’s presentation, FAILCamp and RubyFringe — I’m happy to return to Enumerating Enumerable, the article series in which I attempt to do a better job at documenting Ruby’s Enumerable module than Ruby-Doc.org does.

In this article, the eighth in the series, I’m going to cover a method introduced in Ruby 1.9: drop_while.

I’m going through the Enumerable‘s methods in alphabetical order. If you missed any of the earlier articles, I’ve listed them all below:

  1. all?
  2. any?
  3. collect / map
  4. count
  5. cycle
  6. detect / find
  7. drop

Enumerable#drop_while Quick Summary

Graphic representation of the \"drop_while\" method in Ruby\'s \"Enumerable\" module

In the simplest possible terms Given a collection and a condition, return an array made of the collection’s items, starting the first item that doesn’t meet the condition.
Ruby version 1.9 only
Expects A block containing the condition.
Returns An array made up of the remaining items, if there are any.
RubyDoc.org’s entry Enumerable#drop_while

Enumerable#drop_while and Arrays

When used on an array, drop_while returns a copy of the array created by going through the original array’s items in order, dropping elements until it encounters the an element that does not meet the condition. The resulting array is basically a copy of the original array, starting at the first element that doesn’t meet the condition in the block.

As in many cases, things become clearer with some examples:

Enumerable#drop_while and Hashes

When used on a hash, drop_while effectively:

  • Creates an array based on the hash, with each element in the hash represented as a two-element array where the first element contains the key and the second element containing the corresponding value, then
  • goes through each element in the array, dropping elements until it encounters the first element that doesn’t meet the condition in the block. The resulting array is an array of two-element arrays, starting at the first element that doesn’t meet the condition in the block.

Once again, examples will make this all clear:

Enumerable#drop_while’s Evil Twin, Enumerable#take_while

I’ll cover take_while in detail in a later installment, but for now, an example should suffice:

{ 4 comments }

Enumerating Enumerable: Enumerable#drop

by Joey deVilla on July 10, 2008

Enumerating Enumerable marches on!

This is the seventh article in my series in which I try to do a better job of documenting Ruby’s Enumerable module than Ruby-Doc.org does. If you’ve missed the other articles in the series, they’re listed below:

  1. all?
  2. any?
  3. collect / map
  4. count
  5. cycle
  6. detect / find

In this installment, I cover a method added in Ruby 1.9: drop.

Enumerable#drop Quick Summary

Graphic representation of the \"drop\" method in Ruby\'s \"Enumerable\" module

In the simplest possible terms Given a collection and a number n, create an array made of the items of the collection with the first n items removed.
Ruby version 1.9 only
Expects The number of elements to remove from the start of the collection.
Returns An array made up of the remaining items, if there are any./td>
RubyDoc.org’s entry Enumerable#drop

Enumerable#drop and Arrays

With an array, drop takes a number n as an argument and returns an array created by removing the first n elements of the array. The resulting array is made up of the remaining elements.

Enumerable#drop and Hashes

With an hash, drop takes a number n as an argument and returns an array created by removing the first n elements of the array (drop is only in Ruby 1.9 and later, where hashes keep the order in which they were defined, so its results are predictable). The resulting array is made up of the remaining elements, with each element converted into a two-element array where element 0 is the key and element 1 is the corresponding value.

Enumerable#take: Enumerable#drop’s Evil Twin

I’ll cover take in detail in a later installment, but for now, an example should suffice:

{ 5 comments }

Here’s another article in the Enumerating Enumerable series, in which I attempt to improve upon RubyDoc.org’s documentation for the Enumerable module, which I find rather lacking. If you’ve missed the previous articles in the series, I’ve listed them below:

  1. all?
  2. any?
  3. collect / map
  4. count
  5. cycle

This installment covers a method that goes by two names: detect or find. I personally prefer find, as it’s shorter and the term I tend to use for its function.

Enumerable#detect/Enumerable#find Quick Summary

Graphic representation of the \"detect\" or \"find\" method in Ruby\'s \"Enumerable\" module.

In the simplest possible terms What’s the first item in the collection that meets the given criteria?
Ruby version 1.8 and 1.9
Expects
  • A block containing the criteria.
  • An optional argument containing a proc that calculates a “default” value — that is, the value to return if no item in the collection matches the criteria.
Returns The first item in the collection that matches the criteria, if one exists.
If no such item exists in the collection, detect/find returns:
  • nil is returned if no argument is provided
  • the value of the argument, if one is provided.
RubyDoc.org’s entry Enumerable#detect / Enumerable#find

Enumerable#detect/Enumerable#find and Arrays

When used on an array without an argument, detect/find passes each item from the collection to the block and…

  • If the current item causes the block to return a value that doesn’t evaluate to false, detect/find stops going through collection and returns the item.
  • If no item in the collection causes the block to return a value that doesn’t evaluate to false, detect/find returns nil.

In the examples that follow, I’ll be using the find method. detect does exactly the same thing; it’s just that I prefer find.

Using the optional argument is a topic big enough to merit its own section, which appears later in this article.

Enumerable#detect/Enumerable#find and Hashes

When used on a hash and a block is provided, detect/find passes each key/value pair in the hash to the block, which you can “catch” as either:

  1. A two-element array, with the key as element 0 and its corresponding value as element 1, or
  2. Two separate items, with the key as the first item and its corresponding value as the second item.

When used on a hash without an argument, detect/find passes each item from the collection to the block and…

  • If the current item causes the block to return a value that doesn’t evaluate to false, detect/find stops going through collection and returns the item.
  • If no item in the collection causes the block to return a value that doesn’t evaluate to false, detect/find returns nil.

Using Enumerable#detect/Enumerable#find with the Optional Argument

detect/find‘s optional argument lets you specify a proc or lambda whose return value will be the result in cases where no object in the collection matches the criteria.

(Unfortunately, a complete discussion of procs and lambdas is beyond the scope of this article. I highly recommend looking at Eli Bendersky’s very informative article, Understanding Ruby blocks, Procs and methods.)

I think that the optional argument is best explained through examples…

To see a “real” application of detect/find's optional argument, see this Ruby Quiz problem.

{ 3 comments }

Enumerating Enumerable: Enumerable#cycle

by Joey deVilla on July 6, 2008

Welcome to another installment of Enumerating Enumerable, my series of articles in which I attempt to improve upon RubyDoc.org’s documentation for the Enumerable module. So far, I’ve covered the following methods in this series:

  1. all?
  2. any?
  3. collect / map
  4. count

In this installment, I’m going to cover a method added into Enumerable in Ruby 1.9: Enumerable#cycle. It’s particularly poorly-documented in RubyDoc.org, and there isn’t much written about it anywhere else.

Enumerable#cycle Quick Summary

Graphic representation of the \"cycle\" method in Ruby\'s \"Enumerable\" class.

In the simplest possible terms Given a collection, creates an infinitely-repeating ordered source of its items.
Ruby version 1.9 only
Expects An optional block to act on the items in the infinitely repeating until the break statement is encountered.
Returns An Enumerable::Enumerator that acts as the infinite source of the collection’s items.
RubyDoc.org’s entry Enumerable#cycle

Enumerable#cycle and Arrays

When used on an array and a block is provided, cycle passes each item to the block. Once the last array item has been passed to the block, cycle starts over again at the beginning of the array. cycle goes through the array forever unless it encounters a break statement in the block.

The better use for cycle is when you use it to create an object that spits out the next item in a repeating sequence.

How about one more example? We’ll use Enumerable‘s zip method, an array of dinner items and the “days of the week” cycle object to create a meal plan:

Enumerable#cycle and Hashes

When used on a hash and a block is provided, collect and map pass each key/value pair in the hash to the block, which you can “catch” as either:

  1. A two-element array, with the key as element 0 and its corresponding value as element 1, or
  2. Two separate items, with the key as the first item and its corresponding value as the second item.

Each key/value pair is passed to the block, where the operation in the block is performed on the item. Once the last hash item has been passed to the block, cycle starts over again at the beginning of the hash. cycle goes through the hash forever unless it encounters a break statement in the block.

We can use the same technique that we used with arrays and use cycle to create an object that spits out the next item in a cycling hash. Each time we get an item from the object, it comes in the form of a two-element array where the first element is the key and the second element is the corresponding value.

Let’s try one more example! In this one, we’ll use cycle to create three different enumerators — two made from arrays, one from a hash — to assign cooking chores for the Enterprise-D crew for the next ten days.

{ 5 comments }