module Enumerable

What’s Here

Module Enumerable provides methods that are useful to a collection class for:

Methods for Querying

These methods return information about the Enumerable other than the elements themselves:

  • member? (aliased as include?): Returns true if self == object, false otherwise.

  • all?: Returns true if all elements meet a specified criterion; false otherwise.

  • any?: Returns true if any element meets a specified criterion; false otherwise.

  • none?: Returns true if no element meets a specified criterion; false otherwise.

  • one?: Returns true if exactly one element meets a specified criterion; false otherwise.

  • count: Returns the count of elements, based on an argument or block criterion, if given.

  • tally: Returns a new Hash containing the counts of occurrences of each element.

Methods for Fetching

These methods return entries from the Enumerable, without modifying it:

Leading, trailing, or all elements:

  • to_a (aliased as entries): Returns all elements.

  • first: Returns the first element or leading elements.

  • take: Returns a specified number of leading elements.

  • drop: Returns a specified number of trailing elements.

  • take_while: Returns leading elements as specified by the given block.

  • drop_while: Returns trailing elements as specified by the given block.

Minimum and maximum value elements:

  • min: Returns the elements whose values are smallest among the elements, as determined by <=> or a given block.

  • max: Returns the elements whose values are largest among the elements, as determined by <=> or a given block.

  • minmax: Returns a 2-element Array containing the smallest and largest elements.

  • min_by: Returns the smallest element, as determined by the given block.

  • max_by: Returns the largest element, as determined by the given block.

  • minmax_by: Returns the smallest and largest elements, as determined by the given block.

Groups, slices, and partitions:

  • group_by: Returns a Hash that partitions the elements into groups.

  • partition: Returns elements partitioned into two new Arrays, as determined by the given block.

  • slice_after: Returns a new Enumerator whose entries are a partition of self, based either on a given object or a given block.

  • slice_before: Returns a new Enumerator whose entries are a partition of self, based either on a given object or a given block.

  • slice_when: Returns a new Enumerator whose entries are a partition of self based on the given block.

  • chunk: Returns elements organized into chunks as specified by the given block.

  • chunk_while: Returns elements organized into chunks as specified by the given block.

Methods for Searching and Filtering

These methods return elements that meet a specified criterion:

  • find (aliased as detect): Returns an element selected by the block.

  • find_all (aliased as filter, select): Returns elements selected by the block.

  • find_index: Returns the index of an element selected by a given object or block.

  • reject: Returns elements not rejected by the block.

  • uniq: Returns elements that are not duplicates.

Methods for Sorting

These methods return elements in sorted order:

  • sort: Returns the elements, sorted by <=> or the given block.

  • sort_by: Returns the elements, sorted by the given block.

Methods for Iterating

  • each_entry: Calls the block with each successive element (slightly different from each).

  • each_with_index: Calls the block with each successive element and its index.

  • each_with_object: Calls the block with each successive element and a given object.

  • each_slice: Calls the block with successive non-overlapping slices.

  • each_cons: Calls the block with successive overlapping slices. (different from each_slice).

  • reverse_each: Calls the block with each successive element, in reverse order.

Other Methods

  • collect (aliased as map): Returns objects returned by the block.

  • filter_map: Returns truthy objects returned by the block.

  • flat_map (aliased as collect_concat): Returns flattened objects returned by the block.

  • grep: Returns elements selected by a given object or objects returned by a given block.

  • grep_v: Returns elements not selected by a given object or objects returned by a given block.

  • inject (aliased as reduce): Returns the object formed by combining all elements.

  • sum: Returns the sum of the elements, using method +.

  • zip: Combines each element with elements from other enumerables; returns the n-tuples or calls the block with each.

  • cycle: Calls the block with each element, cycling repeatedly.

Usage

To use module Enumerable in a collection class:

  • Include it:

    include Enumerable
    
  • Implement method each which must yield successive elements of the collection. The method will be called by almost any Enumerable method.

Example:

class Foo
  include Enumerable
  def each
    yield 1
    yield 1, 2
    yield
  end
end
Foo.new.each_entry{ |element| p element }

Output:

1
[1, 2]
nil

Enumerable in Ruby Classes

These Ruby core classes include (or extend) Enumerable:

These Ruby standard library classes include Enumerable:

  • CSV

  • CSV::Table

  • CSV::Row

  • Set

Virtually all methods in Enumerable call method each in the including class:

  • Hash#each yields the next key-value pair as a 2-element Array.

  • Struct#each yields the next name-value pair as a 2-element Array.

  • For the other classes above, each yields the next object from the collection.

About the Examples

The example code snippets for the Enumerable methods:

  • Always show the use of one or more Array-like classes (often Array itself).

  • Sometimes show the use of a Hash-like class. For some methods, though, the usage would not make sense, and so it is not shown. Example: tally would find exactly one of each Hash entry.

Extended Methods

A Enumerable class may define extended methods. This section describes the standard behavior of extension methods for reference purposes.

size

Enumerator has a size method. It uses the size function argument passed to Enumerator.new.

e = Enumerator.new(-> { 3 }) {|y| p y; y.yield :a; y.yield :b; y.yield :c; :z }
p e.size #=> 3
p e.next #=> :a
p e.next #=> :b
p e.next #=> :c
begin
  e.next
rescue StopIteration
  p $!.result #=> :z
end

The result of the size function should represent the number of iterations (i.e., the number of times Enumerator::Yielder#yield is called). In the above example, the block calls yield three times, and the size function, +-> { 3 }+, returns 3 accordingly. The result of the size function can be an integer, Float::INFINITY, or nil. An integer means the exact number of times yield will be called, as shown above. Float::INFINITY indicates an infinite number of yield calls. nil means the number of yield calls is difficult or impossible to determine.

Many iteration methods return an Enumerator object with an appropriate size function if no block is given.

Examples:

["a", "b", "c"].each.size #=> 3
{a: "x", b: "y", c: "z"}.each.size #=> 3
(0..20).to_a.permutation.size #=> 51090942171709440000
loop.size #=> Float::INFINITY
(1..100).drop_while.size #=> nil  # size depends on the block's behavior
STDIN.each.size #=> nil # cannot be computed without consuming input
File.open("/etc/resolv.conf").each.size #=> nil # cannot be computed without reading the file

The behavior of size for Range-based enumerators depends on the begin element:

  • If the begin element is an Integer, the size method returns an Integer or Float::INFINITY.

  • If the begin element is an object with a succ method (other than Integer), size returns nil. (Computing the size would require repeatedly calling succ, which may be too slow.)

  • If the begin element does not have a succ method, size raises a TypeError.

Examples:

(10..42).each.size #=> 33
(10..42.9).each.size #=> 33 (the #end element may be a non-integer numeric)
(10..).each.size #=> Float::INFINITY
("a".."z").each.size #=> nil
("a"..).each.size #=> nil
(1.0..9.0).each.size # raises TypeError (Float does not have #succ)
(..10).each.size # raises TypeError (beginless range has nil as its #begin)

The Enumerable module itself does not define a size method. A class that includes Enumerable may define its own size method. It is recommended that such a size method be consistent with Enumerator#size.

Array and Hash implement size and return values consistent with Enumerator#size. IO and Dir do not define size, which is also consistent because the corresponding enumerator’s size function returns nil.

However, it is not strictly required for a class’s size method to match Enumerator#size. For example, File#size returns the number of bytes in the file, not the number of lines.