# module Enumerable

## What’s Here¶ ↑

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

- Querying

- Fetching

- Searching and Filtering

- Sorting

- Iterating

- And more.…

### Methods for Querying¶ ↑

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

- `include?`, `member?`: 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:

- `entries`, `to_a`: 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`, `detect`: Returns an element selected by the block.

- `find_all`, `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¶ ↑

- `map`, `collect`: Returns objects returned by the block.

- `filter_map`: Returns truthy objects returned by the block.

- `flat_map`, `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 selected by a given object or objects returned by a given block.

- `reduce`, `inject`: 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:

- `ARGF`

- `Array`

- `Dir`

- `Enumerator`

- `ENV` (extends)

- `Hash`

- `IO`

- `Range`

- `Struct`

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.

### Public Instance Methods

all? → true or false click to toggle source
all?(pattern) → true or false
all? {|element| ... } → true or false

Returns whether every element meets a given criterion.

If `self` has no element, returns `true` and argument or block are not used.

With no argument and no block, returns whether every element is truthy:

    (1..4).all?           # => true
    %w[a b c d].all?      # => true
    [1, 2, nil].all?      # => false
    ['a','b', false].all? # => false
    [].all?               # => true

With argument `pattern` and no block, returns whether for each element `element`, `pattern === element`:

    (1..4).all?(Integer)                 # => true
    (1..4).all?(Numeric)                 # => true
    (1..4).all?(Float)                   # => false
    %w[bar baz bat bam].all?(/ba/)       # => true
    %w[bar baz bat bam].all?(/bar/)      # => false
    %w[bar baz bat bam].all?('ba')       # => false
    {foo: 0, bar: 1, baz: 2}.all?(Array) # => true
    {foo: 0, bar: 1, baz: 2}.all?(Hash)  # => false
    [].all?(Integer)                     # => true

With a block given, returns whether the block returns a truthy value for every element:

    (1..4).all? {|element| element < 5 }                    # => true
    (1..4).all? {|element| element < 4 }                    # => false
    {foo: 0, bar: 1, baz: 2}.all? {|key, value| value < 3 } # => true
    {foo: 0, bar: 1, baz: 2}.all? {|key, value| value < 2 } # => false

Related: `any?`, `none?` `one?`.

    static VALUE
    enum_all(int argc, VALUE *argv, VALUE obj)
    {
        struct MEMO *memo = MEMO_ENUM_NEW(Qtrue);
        WARN_UNUSED_BLOCK(argc);
        rb_block_call(obj, id_each, 0, 0, ENUMFUNC(all), (VALUE)memo);
        return memo->v1;
    }

any? → true or false click to toggle source
any?(pattern) → true or false
any? {|element| ... } → true or false

Returns whether any element meets a given criterion.

If `self` has no element, returns `false` and argument or block are not used.

With no argument and no block, returns whether any element is truthy:

    (1..4).any?          # => true
    %w[a b c d].any?     # => true
    [1, false, nil].any? # => true
    [].any?              # => false

With argument `pattern` and no block, returns whether for any element `element`, `pattern === element`:

    [nil, false, 0].any?(Integer)        # => true
    [nil, false, 0].any?(Numeric)        # => true
    [nil, false, 0].any?(Float)          # => false
    %w[bar baz bat bam].any?(/m/)        # => true
    %w[bar baz bat bam].any?(/foo/)      # => false
    %w[bar baz bat bam].any?('ba')       # => false
    {foo: 0, bar: 1, baz: 2}.any?(Array) # => true
    {foo: 0, bar: 1, baz: 2}.any?(Hash)  # => false
    [].any?(Integer)                     # => false

With a block given, returns whether the block returns a truthy value for any element:

    (1..4).any? {|element| element < 2 }                    # => true
    (1..4).any? {|element| element < 1 }                    # => false
    {foo: 0, bar: 1, baz: 2}.any? {|key, value| value < 1 } # => true
    {foo: 0, bar: 1, baz: 2}.any? {|key, value| value < 0 } # => false

Related: `all?`, `none?`, `one?`.

    static VALUE
    enum_any(int argc, VALUE *argv, VALUE obj)
    {
        struct MEMO *memo = MEMO_ENUM_NEW(Qfalse);
        WARN_UNUSED_BLOCK(argc);
        rb_block_call(obj, id_each, 0, 0, ENUMFUNC(any), (VALUE)memo);
        return memo->v1;
    }

chain(*enums) → enumerator click to toggle source

Returns an enumerator object generated from this enumerator and given enumerables.

    e = (1..3).chain([4, 5])
    e.to_a #=> [1, 2, 3, 4, 5]

    static VALUE
    enum_chain(int argc, VALUE *argv, VALUE obj)
    {
        VALUE enums = rb_ary_new_from_values(1, &obj);
        rb_ary_cat(enums, argv, argc);
        return new_enum_chain(enums);
    }

chunk {|array| ... } → enumerator click to toggle source

Each element in the returned enumerator is a 2-element array consisting of:

- A value returned by the block.

- An array (“chunk”) containing the element for which that value was returned, and all following elements for which the block returned the same value:

So that:

- Each block return value that is different from its predecessor begins a new chunk.

- Each block return value that is the same as its predecessor continues the same chunk.

Example:

    e = (0..10).chunk {|i| (i / 3).floor } # => #<Enumerator: ...>
    # The enumerator elements.
    e.next # => [0, [0, 1, 2]]
    e.next # => [1, [3, 4, 5]]
    e.next # => [2, [6, 7, 8]]
    e.next # => [3, [9, 10]]

Method `chunk` is especially useful for an enumerable that is already sorted. This example counts words for each initial letter in a large array of words:

    # Get sorted words from a web page.
    url = 'https://raw.githubusercontent.com/eneko/data-repository/master/data/words.txt'
    words = URI::open(url).readlines
    # Make chunks, one for each letter.
    e = words.chunk {|word| word.upcase[0] } # => #<Enumerator: ...>
    # Display 'A' through 'F'.
    e.each {|c, words| p [c, words.length]; break if c == 'F' }

Output:

    ["A", 17096]
    ["B", 11070]
    ["C", 19901]
    ["D", 10896]
    ["E", 8736]
    ["F", 6860]

You can use the special symbol `:_alone` to force an element into its own separate chuck:

    a = [0, 0, 1, 1]
    e = a.chunk{|i| i.even? ? :_alone : true }
    e.to_a # => [[:_alone, [0]], [:_alone, [0]], [true, [1, 1]]]

For example, you can put each line that contains a URL into its own chunk:

    pattern = /http/
    open(filename) { |f|
      f.chunk { |line| line =~ pattern ? :_alone : true }.each { |key, lines|
        pp lines
      }
    }

You can use the special symbol `:_separator` or `nil` to force an element to be ignored (not included in any chunk):

    a = [0, 0, -1, 1, 1]
    e = a.chunk{|i| i < 0 ? :_separator : true }
    e.to_a # => [[true, [0, 0]], [true, [1, 1]]]

Note that the separator does end the chunk:

    a = [0, 0, -1, 1, -1, 1]
    e = a.chunk{|i| i < 0 ? :_separator : true }
    e.to_a # => [[true, [0, 0]], [true, [1]], [true, [1]]]

For example, the sequence of hyphens in svn log can be eliminated as follows:

    sep = "-"*72 + "\n"
    IO.popen("svn log README") { |f|
      f.chunk { |line|
        line != sep || nil
      }.each { |_, lines|
        pp lines
      }
    }
    #=> ["r20018 | knu | 2008-10-29 13:20:42 +0900 (Wed, 29 Oct 2008) | 2 lines\n",
    #    "\n",
    #    "* README, README.ja: Update the portability section.\n",
    #    "\n"]
    #   ["r16725 | knu | 2008-05-31 23:34:23 +0900 (Sat, 31 May 2008) | 2 lines\n",
    #    "\n",
    #    "* README, README.ja: Add a note about default C flags.\n",
    #    "\n"]
    #   ...

Paragraphs separated by empty lines can be parsed as follows:

    File.foreach("README").chunk { |line|
      /\A\s*\z/ !~ line || nil
    }.each { |_, lines|
      pp lines
    }

    static VALUE
    enum_chunk(VALUE enumerable)
    {
        VALUE enumerator;

        RETURN_SIZED_ENUMERATOR(enumerable, 0, 0, enum_size);

        enumerator = rb_obj_alloc(rb_cEnumerator);
        rb_ivar_set(enumerator, id_chunk_enumerable, enumerable);
        rb_ivar_set(enumerator, id_chunk_categorize, rb_block_proc());
        rb_block_call(enumerator, idInitialize, 0, 0, chunk_i, enumerator);
        return enumerator;
    }

chunk_while {|elt_before, elt_after| bool } → an_enumerator click to toggle source

Creates an enumerator for each chunked elements. The beginnings of chunks are defined by the block.

This method splits each chunk using adjacent elements, elt_before and elt_after, in the receiver enumerator. This method split chunks between elt_before and elt_after where the block returns `false`.

The block is called the length of the receiver enumerator minus one.

The result enumerator yields the chunked elements as an array. So `each` method can be called as follows:

    enum.chunk_while { |elt_before, elt_after| bool }.each { |ary| ... }

Other methods of the `Enumerator` class and `Enumerable` module, such as `to_a`, `map`, etc., are also usable.

For example, one-by-one increasing subsequence can be chunked as follows:

    a = [1,2,4,9,10,11,12,15,16,19,20,21]
    b = a.chunk_while {|i, j| i+1 == j }
    p b.to_a #=> [[1, 2], [4], [9, 10, 11, 12], [15, 16], [19, 20, 21]]
    c = b.map {|a| a.length < 3 ? a : "#{a.first}-#{a.last}" }
    p c #=> [[1, 2], [4], "9-12", [15, 16], "19-21"]
    d = c.join(",")
    p d #=> "1,2,4,9-12,15,16,19-21"

Increasing (non-decreasing) subsequence can be chunked as follows:

    a = [0, 9, 2, 2, 3, 2, 7, 5, 9, 5]
    p a.chunk_while {|i, j| i <= j }.to_a
    #=> [[0, 9], [2, 2, 3], [2, 7], [5, 9], [5]]

Adjacent evens and odds can be chunked as follows: (`Enumerable#chunk` is another way to do it.)

    a = [7, 5, 9, 2, 0, 7, 9, 4, 2, 0]
    p a.chunk_while {|i, j| i.even? == j.even? }.to_a
    #=> [[7, 5, 9], [2, 0], [7, 9], [4, 2, 0]]

`Enumerable#slice_when` does the same, except splitting when the block returns `true` instead of `false`.

    static VALUE
    enum_chunk_while(VALUE enumerable)
    {
        VALUE enumerator;
        VALUE pred;

        pred = rb_block_proc();

        enumerator = rb_obj_alloc(rb_cEnumerator);
        rb_ivar_set(enumerator, id_slicewhen_enum, enumerable);
        rb_ivar_set(enumerator, id_slicewhen_pred, pred);
        rb_ivar_set(enumerator, id_slicewhen_inverted, Qtrue);

        rb_block_call(enumerator, idInitialize, 0, 0, slicewhen_i, enumerator);
        return enumerator;
    }

collect
Also aliased as: map
collect_concat
Alias for: flat_map
compact → array click to toggle source

Returns an array of all non-`nil` elements:

    a = [nil, 0, nil, 'a', false, nil, false, nil, 'a', nil, 0, nil]
    a.compact # => [0, "a", false, false, "a", 0]

    static VALUE
    enum_compact(VALUE obj)
    {
        VALUE ary;

        ary = rb_ary_new();
        rb_block_call(obj, id_each, 0, 0, compact_i, ary);

        return ary;
    }

count → integer click to toggle source
count(object) → integer
count {|element| ... } → integer

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

With no argument and no block given, returns the number of elements:

    [0, 1, 2].count                # => 3
    {foo: 0, bar: 1, baz: 2}.count # => 3

With argument `object` given, returns the number of elements that are `==` to `object`:

    [0, 1, 2, 1].count(1)           # => 2

With a block given, calls the block with each element and returns the number of elements for which the block returns a truthy value:

    [0, 1, 2, 3].count {|element| element < 2}              # => 2
    {foo: 0, bar: 1, baz: 2}.count {|key, value| value < 2} # => 2

    static VALUE
    enum_count(int argc, VALUE *argv, VALUE obj)
    {
        VALUE item = Qnil;
        struct MEMO *memo;
        rb_block_call_func *func;

        if (argc == 0) {
            if (rb_block_given_p()) {
                func = count_iter_i;
            }
            else {
                func = count_all_i;
            }
        }
        else {
            rb_scan_args(argc, argv, "1", &item);
            if (rb_block_given_p()) {
                rb_warn("given block not used");
            }
            func = count_i;
        }

        memo = MEMO_NEW(item, 0, 0);
        rb_block_call(obj, id_each, 0, 0, func, (VALUE)memo);
        return imemo_count_value(memo);
    }

cycle(n = nil) {|element| ...} → nil click to toggle source
cycle(n = nil) → enumerator

When called with positive integer argument `n` and a block, calls the block with each element, then does so again, until it has done so `n` times; returns `nil`:

    a = []
    (1..4).cycle(3) {|element| a.push(element) } # => nil
    a # => [1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]
    a = []
    ('a'..'d').cycle(2) {|element| a.push(element) }
    a # => ["a", "b", "c", "d", "a", "b", "c", "d"]
    a = []
    {foo: 0, bar: 1, baz: 2}.cycle(2) {|element| a.push(element) }
    a # => [[:foo, 0], [:bar, 1], [:baz, 2], [:foo, 0], [:bar, 1], [:baz, 2]]

If count is zero or negative, does not call the block.

When called with a block and `n` is `nil`, cycles forever.

When no block is given, returns an `Enumerator`.

    static VALUE
    enum_cycle(int argc, VALUE *argv, VALUE obj)
    {
        VALUE ary;
        VALUE nv = Qnil;
        long n, i, len;

        rb_check_arity(argc, 0, 1);

        RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_cycle_size);
        if (!argc || NIL_P(nv = argv[0])) {
            n = -1;
        }
        else {
            n = NUM2LONG(nv);
            if (n <= 0) return Qnil;
        }
        ary = rb_ary_new();
        RBASIC_CLEAR_CLASS(ary);
        rb_block_call(obj, id_each, 0, 0, cycle_i, ary);
        len = RARRAY_LEN(ary);
        if (len == 0) return Qnil;
        while (n < 0 || 0 < --n) {
            for (i=0; i<len; i++) {
                enum_yield_array(RARRAY_AREF(ary, i));
            }
        }
        return Qnil;
    }

detect
Alias for: find
drop(n) → array click to toggle source

For positive integer `n`, returns an array containing all but the first `n` elements:

    r = (1..4)
    r.drop(3)  # => [4]
    r.drop(2)  # => [3, 4]
    r.drop(1)  # => [2, 3, 4]
    r.drop(0)  # => [1, 2, 3, 4]
    r.drop(50) # => []

    h = {foo: 0, bar: 1, baz: 2, bat: 3}
    h.drop(2) # => [[:baz, 2], [:bat, 3]]

    static VALUE
    enum_drop(VALUE obj, VALUE n)
    {
        VALUE result;
        struct MEMO *memo;
        long len = NUM2LONG(n);

        if (len < 0) {
            rb_raise(rb_eArgError, "attempt to drop negative size");
        }

        result = rb_ary_new();
        memo = MEMO_NEW(result, 0, len);
        rb_block_call(obj, id_each, 0, 0, drop_i, (VALUE)memo);
        return result;
    }

drop_while {|element| ... } → array click to toggle source
drop_while → enumerator

Calls the block with successive elements as long as the block returns a truthy value; returns an array of all elements after that point:

    (1..4).drop_while{|i| i < 3 } # => [3, 4]
    h = {foo: 0, bar: 1, baz: 2}
    a = h.drop_while{|element| key, value = *element; value < 2 }
    a # => [[:baz, 2]]

With no block given, returns an `Enumerator`.

    static VALUE
    enum_drop_while(VALUE obj)
    {
        VALUE result;
        struct MEMO *memo;

        RETURN_ENUMERATOR(obj, 0, 0);
        result = rb_ary_new();
        memo = MEMO_NEW(result, 0, FALSE);
        rb_block_call(obj, id_each, 0, 0, drop_while_i, (VALUE)memo);
        return result;
    }

each_cons(n) { ... } → self click to toggle source
each_cons(n) → enumerator

Calls the block with each successive overlapped `n`-tuple of elements; returns `self`:

    a = []
    (1..5).each_cons(3) {|element| a.push(element) }
    a # => [[1, 2, 3], [2, 3, 4], [3, 4, 5]]

    a = []
    h = {foo: 0,  bar: 1, baz: 2, bam: 3}
    h.each_cons(2) {|element| a.push(element) }
    a # => [[[:foo, 0], [:bar, 1]], [[:bar, 1], [:baz, 2]], [[:baz, 2], [:bam, 3]]]

With no block given, returns an `Enumerator`.

    static VALUE
    enum_each_cons(VALUE obj, VALUE n)
    {
        long size = NUM2LONG(n);
        struct MEMO *memo;
        int arity;

        if (size <= 0) rb_raise(rb_eArgError, "invalid size");
        RETURN_SIZED_ENUMERATOR(obj, 1, &n, enum_each_cons_size);
        arity = rb_block_arity();
        if (enum_size_over_p(obj, size)) return obj;
        memo = MEMO_NEW(rb_ary_new2(size), dont_recycle_block_arg(arity), size);
        rb_block_call(obj, id_each, 0, 0, each_cons_i, (VALUE)memo);

        return obj;
    }

each_entry(*args) {|element| ... } → self click to toggle source
each_entry(*args) → enumerator

Calls the given block with each element, converting multiple values from yield to an array; returns `self`:

    a = []
    (1..4).each_entry {|element| a.push(element) } # => 1..4
    a # => [1, 2, 3, 4]

    a = []
    h = {foo: 0, bar: 1, baz:2}
    h.each_entry {|element| a.push(element) }
    # => {:foo=>0, :bar=>1, :baz=>2}
    a # => [[:foo, 0], [:bar, 1], [:baz, 2]]

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

Output:

    1
    [1, 2]
    nil

With no block given, returns an `Enumerator`.

    static VALUE
    enum_each_entry(int argc, VALUE *argv, VALUE obj)
    {
        RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);
        rb_block_call(obj, id_each, argc, argv, each_val_i, 0);
        return obj;
    }

each_slice(n) { ... } → self click to toggle source
each_slice(n) → enumerator

Calls the block with each successive disjoint `n`-tuple of elements; returns `self`:

    a = []
    (1..10).each_slice(3) {|tuple| a.push(tuple) }
    a # => [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]

    a = []
    h = {foo: 0, bar: 1, baz: 2, bat: 3, bam: 4}
    h.each_slice(2) {|tuple| a.push(tuple) }
    a # => [[[:foo, 0], [:bar, 1]], [[:baz, 2], [:bat, 3]], [[:bam, 4]]]

With no block given, returns an `Enumerator`.

    static VALUE
    enum_each_slice(VALUE obj, VALUE n)
    {
        long size = NUM2LONG(n);
        VALUE ary;
        struct MEMO *memo;
        int arity;

        if (size <= 0) rb_raise(rb_eArgError, "invalid slice size");
        RETURN_SIZED_ENUMERATOR(obj, 1, &n, enum_each_slice_size);
        size = limit_by_enum_size(obj, size);
        ary = rb_ary_new2(size);
        arity = rb_block_arity();
        memo = MEMO_NEW(ary, dont_recycle_block_arg(arity), size);
        rb_block_call(obj, id_each, 0, 0, each_slice_i, (VALUE)memo);
        ary = memo->v1;
        if (RARRAY_LEN(ary) > 0) rb_yield(ary);

        return obj;
    }

each_with_index(*args) {|element, i| ..... } → self click to toggle source
each_with_index(*args) → enumerator

With a block given, calls the block with each element and its index; returns `self`:

    h = {}
    (1..4).each_with_index {|element, i| h[element] = i } # => 1..4
    h # => {1=>0, 2=>1, 3=>2, 4=>3}

    h = {}
    %w[a b c d].each_with_index {|element, i| h[element] = i }
    # => ["a", "b", "c", "d"]
    h # => {"a"=>0, "b"=>1, "c"=>2, "d"=>3}

    a = []
    h = {foo: 0, bar: 1, baz: 2}
    h.each_with_index {|element, i| a.push([i, element]) }
    # => {:foo=>0, :bar=>1, :baz=>2}
    a # => [[0, [:foo, 0]], [1, [:bar, 1]], [2, [:baz, 2]]]

With no block given, returns an `Enumerator`.

    static VALUE
    enum_each_with_index(int argc, VALUE *argv, VALUE obj)
    {
        struct MEMO *memo;

        RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);

        memo = MEMO_NEW(0, 0, 0);
        rb_block_call(obj, id_each, argc, argv, each_with_index_i, (VALUE)memo);
        return obj;
    }

each_with_object(object) { |(*args), memo_object| ... } → object click to toggle source
each_with_object(object) → enumerator

Calls the block once for each element, passing both the element and the given object:

    (1..4).each_with_object([]) {|i, a| a.push(i**2) }
    # => [1, 4, 9, 16]

    {foo: 0, bar: 1, baz: 2}.each_with_object({}) {|(k, v), h| h[v] = k }
    # => {0=>:foo, 1=>:bar, 2=>:baz}

With no block given, returns an `Enumerator`.

    static VALUE
    enum_each_with_object(VALUE obj, VALUE memo)
    {
        RETURN_SIZED_ENUMERATOR(obj, 1, &memo, enum_size);

        rb_block_call(obj, id_each, 0, 0, each_with_object_i, memo);

        return memo;
    }

entries
Alias for: to_a
filter
Alias for: find_all
filter_map {|element| ... } → array click to toggle source
filter_map → enumerator

Returns an array containing truthy elements returned by the block.

With a block given, calls the block with successive elements; returns an array containing each truthy value returned by the block:

    (0..9).filter_map {|i| i * 2 if i.even? }                              # => [0, 4, 8, 12, 16]
    {foo: 0, bar: 1, baz: 2}.filter_map {|key, value| key if value.even? } # => [:foo, :baz]

When no block given, returns an `Enumerator`.

    static VALUE
    enum_filter_map(VALUE obj)
    {
        VALUE ary;

        RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);

        ary = rb_ary_new();
        rb_block_call(obj, id_each, 0, 0, filter_map_i, ary);

        return ary;
    }

find(if_none_proc = nil) {|element| ... } → object or nil click to toggle source
find(if_none_proc = nil) → enumerator

Returns the first element for which the block returns a truthy value.

With a block given, calls the block with successive elements of the collection; returns the first element for which the block returns a truthy value:

    (0..9).find {|element| element > 2}                # => 3

If no such element is found, calls `if_none_proc` and returns its return value.

    (0..9).find(proc {false}) {|element| element > 12} # => false
    {foo: 0, bar: 1, baz: 2}.find {|key, value| key.start_with?('b') }            # => [:bar, 1]
    {foo: 0, bar: 1, baz: 2}.find(proc {[]}) {|key, value| key.start_with?('c') } # => []

With no block given, returns an `Enumerator`.

    static VALUE
    enum_find(int argc, VALUE *argv, VALUE obj)
    {
        struct MEMO *memo;
        VALUE if_none;

        if_none = rb_check_arity(argc, 0, 1) ? argv[0] : Qnil;
        RETURN_ENUMERATOR(obj, argc, argv);
        memo = MEMO_NEW(Qundef, 0, 0);
        rb_block_call(obj, id_each, 0, 0, find_i, (VALUE)memo);
        if (memo->u3.cnt) {
            return memo->v1;
        }
        if (!NIL_P(if_none)) {
            return rb_funcallv(if_none, id_call, 0, 0);
        }
        return Qnil;
    }

Also aliased as: detect
find_all
Also aliased as: select, filter
find_index(object) → integer or nil click to toggle source
find_index {|element| ... } → integer or nil
find_index → enumerator

Returns the index of the first element that meets a specified criterion, or `nil` if no such element is found.

With argument `object` given, returns the index of the first element that is `==` `object`:

    ['a', 'b', 'c', 'b'].find_index('b') # => 1

With a block given, calls the block with successive elements; returns the first element for which the block returns a truthy value:

    ['a', 'b', 'c', 'b'].find_index {|element| element.start_with?('b') } # => 1
    {foo: 0, bar: 1, baz: 2}.find_index {|key, value| value > 1 }         # => 2

With no argument and no block given, returns an `Enumerator`.

    static VALUE
    enum_find_index(int argc, VALUE *argv, VALUE obj)
    {
        struct MEMO *memo;  /* [return value, current index, ] */
        VALUE condition_value = Qnil;
        rb_block_call_func *func;

        if (argc == 0) {
            RETURN_ENUMERATOR(obj, 0, 0);
            func = find_index_iter_i;
        }
        else {
            rb_scan_args(argc, argv, "1", &condition_value);
            if (rb_block_given_p()) {
                rb_warn("given block not used");
            }
            func = find_index_i;
        }

        memo = MEMO_NEW(Qnil, condition_value, 0);
        rb_block_call(obj, id_each, 0, 0, func, (VALUE)memo);
        return memo->v1;
    }

first → element or nil click to toggle source
first(n) → array

Returns the first element or elements.

With no argument, returns the first element, or `nil` if there is none:

    (1..4).first                   # => 1
    %w[a b c].first                # => "a"
    {foo: 1, bar: 1, baz: 2}.first # => [:foo, 1]
    [].first                       # => nil

With integer argument `n`, returns an array containing the first `n` elements that exist:

    (1..4).first(2)                   # => [1, 2]
    %w[a b c d].first(3)              # => ["a", "b", "c"]
    %w[a b c d].first(50)             # => ["a", "b", "c", "d"]
    {foo: 1, bar: 1, baz: 2}.first(2) # => [[:foo, 1], [:bar, 1]]
    [].first(2)                       # => []

    static VALUE
    enum_first(int argc, VALUE *argv, VALUE obj)
    {
        struct MEMO *memo;
        rb_check_arity(argc, 0, 1);
        if (argc > 0) {
            return enum_take(obj, argv[0]);
        }
        else {
            memo = MEMO_NEW(Qnil, 0, 0);
            rb_block_call(obj, id_each, 0, 0, first_i, (VALUE)memo);
            return memo->v1;
        }
    }

flat_map {|element| ... } → array click to toggle source
flat_map → enumerator

Returns an array of flattened objects returned by the block.

With a block given, calls the block with successive elements; returns a flattened array of objects returned by the block:

    [0, 1, 2, 3].flat_map {|element| -element }                    # => [0, -1, -2, -3]
    [0, 1, 2, 3].flat_map {|element| [element, -element] }         # => [0, 0, 1, -1, 2, -2, 3, -3]
    [[0, 1], [2, 3]].flat_map {|e| e + [100] }                     # => [0, 1, 100, 2, 3, 100]
    {foo: 0, bar: 1, baz: 2}.flat_map {|key, value| [key, value] } # => [:foo, 0, :bar, 1, :baz, 2]

With no block given, returns an `Enumerator`.

Alias: `collect_concat`.

    static VALUE
    enum_flat_map(VALUE obj)
    {
        VALUE ary;

        RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);

        ary = rb_ary_new();
        rb_block_call(obj, id_each, 0, 0, flat_map_i, ary);

        return ary;
    }

Also aliased as: collect_concat
grep(pattern) → array click to toggle source
grep(pattern) {|element| ... } → array

Returns an array of objects based elements of `self` that match the given pattern.

With no block given, returns an array containing each element for which `pattern === element` is `true`:

    a = ['foo', 'bar', 'car', 'moo']
    a.grep(/ar/)                   # => ["bar", "car"]
    (1..10).grep(3..8)             # => [3, 4, 5, 6, 7, 8]
    ['a', 'b', 0, 1].grep(Integer) # => [0, 1]

With a block given, calls the block with each matching element and returns an array containing each object returned by the block:

    a = ['foo', 'bar', 'car', 'moo']
    a.grep(/ar/) {|element| element.upcase } # => ["BAR", "CAR"]

Related: `grep_v`.

    static VALUE
    enum_grep(VALUE obj, VALUE pat)
    {
        return enum_grep0(obj, pat, Qtrue);
    }

grep_v(pattern) → array click to toggle source
grep_v(pattern) {|element| ... } → array

Returns an array of objects based on elements of `self` that don’t match the given pattern.

With no block given, returns an array containing each element for which `pattern === element` is `false`:

    a = ['foo', 'bar', 'car', 'moo']
    a.grep_v(/ar/)                   # => ["foo", "moo"]
    (1..10).grep_v(3..8)             # => [1, 2, 9, 10]
    ['a', 'b', 0, 1].grep_v(Integer) # => ["a", "b"]

With a block given, calls the block with each non-matching element and returns an array containing each object returned by the block:

    a = ['foo', 'bar', 'car', 'moo']
    a.grep_v(/ar/) {|element| element.upcase } # => ["FOO", "MOO"]

Related: `grep`.

    static VALUE
    enum_grep_v(VALUE obj, VALUE pat)
    {
        return enum_grep0(obj, pat, Qfalse);
    }

group_by {|element| ... } → hash click to toggle source
group_by → enumerator

With a block given returns a hash:

- Each key is a return value from the block.

- Each value is an array of those elements for which the block returned that key.

Examples:

    g = (1..6).group_by {|i| i%3 }
    g # => {1=>[1, 4], 2=>[2, 5], 0=>[3, 6]}
    h = {foo: 0, bar: 1, baz: 0, bat: 1}
    g = h.group_by {|key, value| value }
    g # => {0=>[[:foo, 0], [:baz, 0]], 1=>[[:bar, 1], [:bat, 1]]}

With no block given, returns an `Enumerator`.

    static VALUE
    enum_group_by(VALUE obj)
    {
        RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);

        return enum_hashify(obj, 0, 0, group_by_i);
    }

include?(object) → true or false

Returns whether for any element `object == element`:

    (1..4).include?(2)                       # => true
    (1..4).include?(5)                       # => false
    (1..4).include?('2')                     # => false
    %w[a b c d].include?('b')                # => true
    %w[a b c d].include?('2')                # => false
    {foo: 0, bar: 1, baz: 2}.include?(:foo)  # => true
    {foo: 0, bar: 1, baz: 2}.include?('foo') # => false
    {foo: 0, bar: 1, baz: 2}.include?(0)     # => false

Alias for: member?
inject(symbol) → object click to toggle source
inject(initial_operand, symbol) → object
inject {|memo, operand| ... } → object
inject(initial_operand) {|memo, operand| ... } → object

Returns an object formed from operands via either:

- A method named by `symbol`.

- A block to which each operand is passed.

With method-name argument `symbol`, combines operands using the method:

    # Sum, without initial_operand.
    (1..4).inject(:+)     # => 10
    # Sum, with initial_operand.
    (1..4).inject(10, :+) # => 20

With a block, passes each operand to the block:

    # Sum of squares, without initial_operand.
    (1..4).inject {|sum, n| sum + n*n }    # => 30
    # Sum of squares, with initial_operand.
    (1..4).inject(2) {|sum, n| sum + n*n } # => 32

Operands

If argument `initial_operand` is not given, the operands for `inject` are simply the elements of `self`. Example calls and their operands:

- `(1..4).inject(:+)`

    `[1, 2, 3, 4]`.

- `(1...4).inject(:+)`

    `[1, 2, 3]`.

- `('a'..'d').inject(:+)`

    `['a', 'b', 'c', 'd']`.

- `('a'...'d').inject(:+)`

    `['a', 'b', 'c']`.

Examples with first operand (which is `self.first`) of various types:

    # Integer.
    (1..4).inject(:+)                # => 10
    # Float.
    [1.0, 2, 3, 4].inject(:+)        # => 10.0
    # Character.
    ('a'..'d').inject(:+)            # => "abcd"
    # Complex.
    [Complex(1, 2), 3, 4].inject(:+) # => (8+2i)

If argument `initial_operand` is given, the operands for `inject` are that value plus the elements of `self`. Example calls their operands:

- `(1..4).inject(10, :+)`

    `[10, 1, 2, 3, 4]`.

- `(1...4).inject(10, :+)`

    `[10, 1, 2, 3]`.

- `('a'..'d').inject('e', :+)`

    `['e', 'a', 'b', 'c', 'd']`.

- `('a'...'d').inject('e', :+)`

    `['e', 'a', 'b', 'c']`.

Examples with `initial_operand` of various types:

    # Integer.
    (1..4).inject(2, :+)               # => 12
    # Float.
    (1..4).inject(2.0, :+)             # => 12.0
    # String.
    ('a'..'d').inject('foo', :+)       # => "fooabcd"
    # Array.
    %w[a b c].inject(['x'], :push)     # => ["x", "a", "b", "c"]
    # Complex.
    (1..4).inject(Complex(2, 2), :+)   # => (12+2i)

Combination by Given Method

If the method-name argument `symbol` is given, the operands are combined by that method:

- The first and second operands are combined.

- That result is combined with the third operand.

- That result is combined with the fourth operand.

- And so on.

The return value from `inject` is the result of the last combination.

This call to `inject` computes the sum of the operands:

    (1..4).inject(:+) # => 10

Examples with various methods:

    # Integer addition.
    (1..4).inject(:+)                # => 10
    # Integer multiplication.
    (1..4).inject(:*)                # => 24
    # Character range concatenation.
    ('a'..'d').inject('', :+)        # => "abcd"
    # String array concatenation.
    %w[foo bar baz].inject('', :+)   # => "foobarbaz"
    # Hash update.
    h = [{foo: 0, bar: 1}, {baz: 2}, {bat: 3}].inject(:update)
    h # => {:foo=>0, :bar=>1, :baz=>2, :bat=>3}
    # Hash conversion to nested arrays.
    h = {foo: 0, bar: 1}.inject([], :push)
    h # => [[:foo, 0], [:bar, 1]]

Combination by Given Block

If a block is given, the operands are passed to the block:

- The first call passes the first and second operands.

- The second call passes the result of the first call, along with the third operand.

- The third call passes the result of the second call, along with the fourth operand.

- And so on.

The return value from `inject` is the return value from the last block call.

This call to `inject` gives a block that writes the memo and element, and also sums the elements:

    (1..4).inject do |memo, element|
      p "Memo: #{memo}; element: #{element}"
      memo + element
    end # => 10

Output:

    "Memo: 1; element: 2"
    "Memo: 3; element: 3"
    "Memo: 6; element: 4"

    static VALUE
    enum_inject(int argc, VALUE *argv, VALUE obj)
    {
        struct MEMO *memo;
        VALUE init, op;
        rb_block_call_func *iter = inject_i;
        ID id;
        int num_args;

        if (rb_block_given_p()) {
            num_args = rb_scan_args(argc, argv, "02", &init, &op);
        }
        else {
            num_args = rb_scan_args(argc, argv, "11", &init, &op);
        }

        switch (num_args) {
          case 0:
            init = Qundef;
            break;
          case 1:
            if (rb_block_given_p()) {
                break;
            }
            id = rb_check_id(&init);
            op = id ? ID2SYM(id) : init;
            init = Qundef;
            iter = inject_op_i;
            break;
          case 2:
            if (rb_block_given_p()) {
                rb_warning("given block not used");
            }
            id = rb_check_id(&op);
            if (id) op = ID2SYM(id);
            iter = inject_op_i;
            break;
        }

        if (iter == inject_op_i &&
            SYMBOL_P(op) &&
            RB_TYPE_P(obj, T_ARRAY) &&
            rb_method_basic_definition_p(CLASS_OF(obj), id_each)) {
            return ary_inject_op(obj, init, op);
        }

        memo = MEMO_NEW(init, Qnil, op);
        rb_block_call(obj, id_each, 0, 0, iter, (VALUE)memo);
        if (UNDEF_P(memo->v1)) return Qnil;
        return memo->v1;
    }

Also aliased as: reduce
lazy → lazy_enumerator click to toggle source

Returns an `Enumerator::Lazy`, which redefines most `Enumerable` methods to postpone enumeration and enumerate values only on an as-needed basis.

### Example¶ ↑

The following program finds pythagorean triples:

    def pythagorean_triples
      (1..Float::INFINITY).lazy.flat_map {|z|
        (1..z).flat_map {|x|
          (x..z).select {|y|
            x**2 + y**2 == z**2
          }.map {|y|
            [x, y, z]
          }
        }
      }
    end
    # show first ten pythagorean triples
    p pythagorean_triples.take(10).force # take is lazy, so force is needed
    p pythagorean_triples.first(10)      # first is eager
    # show pythagorean triples less than 100
    p pythagorean_triples.take_while { |*, z| z < 100 }.force

    static VALUE
    enumerable_lazy(VALUE obj)
    {
        VALUE result = lazy_to_enum_i(obj, sym_each, 0, 0, lazyenum_size, rb_keyword_given_p());
        /* Qfalse indicates that the Enumerator::Lazy has no method name */
        rb_ivar_set(result, id_method, Qfalse);
        return result;
    }

map {|element| ... } → array
map → enumerator

Returns an array of objects returned by the block.

With a block given, calls the block with successive elements; returns an array of the objects returned by the block:

    (0..4).map {|i| i*i }                               # => [0, 1, 4, 9, 16]
    {foo: 0, bar: 1, baz: 2}.map {|key, value| value*2} # => [0, 2, 4]

With no block given, returns an `Enumerator`.

Alias for: collect
max → element click to toggle source
max(n) → array
max {|a, b| ... } → element
max(n) {|a, b| ... } → array

Returns the element with the maximum element according to a given criterion. The ordering of equal elements is indeterminate and may be unstable.

With no argument and no block, returns the maximum element, using the elements’ own method `<=>` for comparison:

    (1..4).max                   # => 4
    (-4..-1).max                 # => -1
    %w[d c b a].max              # => "d"
    {foo: 0, bar: 1, baz: 2}.max # => [:foo, 0]
    [].max                       # => nil

With positive integer argument `n` given, and no block, returns an array containing the first `n` maximum elements that exist:

    (1..4).max(2)                   # => [4, 3]
    (-4..-1).max(2)                # => [-1, -2]
    %w[d c b a].max(2)              # => ["d", "c"]
    {foo: 0, bar: 1, baz: 2}.max(2) # => [[:foo, 0], [:baz, 2]]
    [].max(2)                       # => []

With a block given, the block determines the maximum elements. The block is called with two elements `a` and `b`, and must return:

- A negative integer if `a < b`.

- Zero if `a == b`.

- A positive integer if `a > b`.

With a block given and no argument, returns the maximum element as determined by the block:

    %w[xxx x xxxx xx].max {|a, b| a.size <=> b.size } # => "xxxx"
    h = {foo: 0, bar: 1, baz: 2}
    h.max {|pair1, pair2| pair1[1] <=> pair2[1] }     # => [:baz, 2]
    [].max {|a, b| a <=> b }                          # => nil

With a block given and positive integer argument `n` given, returns an array containing the first `n` maximum elements that exist, as determined by the block.

    %w[xxx x xxxx xx].max(2) {|a, b| a.size <=> b.size } # => ["xxxx", "xxx"]
    h = {foo: 0, bar: 1, baz: 2}
    h.max(2) {|pair1, pair2| pair1[1] <=> pair2[1] }
    # => [[:baz, 2], [:bar, 1]]
    [].max(2) {|a, b| a <=> b }                          # => []

Related: `min`, `minmax`, `max_by`.

    static VALUE
    enum_max(int argc, VALUE *argv, VALUE obj)
    {
        VALUE memo;
        struct max_t *m = NEW_MEMO_FOR(struct max_t, memo);
        VALUE result;
        VALUE num;

        if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
           return rb_nmin_run(obj, num, 0, 1, 0);

        m->max = Qundef;
        if (rb_block_given_p()) {
            rb_block_call(obj, id_each, 0, 0, max_ii, (VALUE)memo);
        }
        else {
            rb_block_call(obj, id_each, 0, 0, max_i, (VALUE)memo);
        }
        result = m->max;
        if (UNDEF_P(result)) return Qnil;
        return result;
    }

max_by {|element| ... } → element click to toggle source
max_by(n) {|element| ... } → array
max_by → enumerator
max_by(n) → enumerator

Returns the elements for which the block returns the maximum values.

With a block given and no argument, returns the element for which the block returns the maximum value:

    (1..4).max_by {|element| -element }                    # => 1
    %w[a b c d].max_by {|element| -element.ord }           # => "a"
    {foo: 0, bar: 1, baz: 2}.max_by {|key, value| -value } # => [:foo, 0]
    [].max_by {|element| -element }                        # => nil

With a block given and positive integer argument `n` given, returns an array containing the `n` elements for which the block returns maximum values:

    (1..4).max_by(2) {|element| -element }
    # => [1, 2]
    %w[a b c d].max_by(2) {|element| -element.ord }
    # => ["a", "b"]
    {foo: 0, bar: 1, baz: 2}.max_by(2) {|key, value| -value }
    # => [[:foo, 0], [:bar, 1]]
    [].max_by(2) {|element| -element }
    # => []

Returns an `Enumerator` if no block is given.

Related: `max`, `minmax`, `min_by`.

    static VALUE
    enum_max_by(int argc, VALUE *argv, VALUE obj)
    {
        struct MEMO *memo;
        VALUE num;

        rb_check_arity(argc, 0, 1);

        RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);

        if (argc && !NIL_P(num = argv[0]))
            return rb_nmin_run(obj, num, 1, 1, 0);

        memo = MEMO_NEW(Qundef, Qnil, 0);
        rb_block_call(obj, id_each, 0, 0, max_by_i, (VALUE)memo);
        return memo->v2;
    }

member?
Also aliased as: include?
min → element click to toggle source
min(n) → array
min {|a, b| ... } → element
min(n) {|a, b| ... } → array

Returns the element with the minimum element according to a given criterion. The ordering of equal elements is indeterminate and may be unstable.

With no argument and no block, returns the minimum element, using the elements’ own method `<=>` for comparison:

    (1..4).min                   # => 1
    (-4..-1).min                 # => -4
    %w[d c b a].min              # => "a"
    {foo: 0, bar: 1, baz: 2}.min # => [:bar, 1]
    [].min                       # => nil

With positive integer argument `n` given, and no block, returns an array containing the first `n` minimum elements that exist:

    (1..4).min(2)                   # => [1, 2]
    (-4..-1).min(2)                 # => [-4, -3]
    %w[d c b a].min(2)              # => ["a", "b"]
    {foo: 0, bar: 1, baz: 2}.min(2) # => [[:bar, 1], [:baz, 2]]
    [].min(2)                       # => []

With a block given, the block determines the minimum elements. The block is called with two elements `a` and `b`, and must return:

- A negative integer if `a < b`.

- Zero if `a == b`.

- A positive integer if `a > b`.

With a block given and no argument, returns the minimum element as determined by the block:

    %w[xxx x xxxx xx].min {|a, b| a.size <=> b.size } # => "x"
    h = {foo: 0, bar: 1, baz: 2}
    h.min {|pair1, pair2| pair1[1] <=> pair2[1] } # => [:foo, 0]
    [].min {|a, b| a <=> b }                          # => nil

With a block given and positive integer argument `n` given, returns an array containing the first `n` minimum elements that exist, as determined by the block.

    %w[xxx x xxxx xx].min(2) {|a, b| a.size <=> b.size } # => ["x", "xx"]
    h = {foo: 0, bar: 1, baz: 2}
    h.min(2) {|pair1, pair2| pair1[1] <=> pair2[1] }
    # => [[:foo, 0], [:bar, 1]]
    [].min(2) {|a, b| a <=> b }                          # => []

Related: `min_by`, `minmax`, `max`.

    static VALUE
    enum_min(int argc, VALUE *argv, VALUE obj)
    {
        VALUE memo;
        struct min_t *m = NEW_MEMO_FOR(struct min_t, memo);
        VALUE result;
        VALUE num;

        if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
           return rb_nmin_run(obj, num, 0, 0, 0);

        m->min = Qundef;
        if (rb_block_given_p()) {
            rb_block_call(obj, id_each, 0, 0, min_ii, memo);
        }
        else {
            rb_block_call(obj, id_each, 0, 0, min_i, memo);
        }
        result = m->min;
        if (UNDEF_P(result)) return Qnil;
        return result;
    }

min_by {|element| ... } → element click to toggle source
min_by(n) {|element| ... } → array
min_by → enumerator
min_by(n) → enumerator

Returns the elements for which the block returns the minimum values.

With a block given and no argument, returns the element for which the block returns the minimum value:

    (1..4).min_by {|element| -element }                    # => 4
    %w[a b c d].min_by {|element| -element.ord }           # => "d"
    {foo: 0, bar: 1, baz: 2}.min_by {|key, value| -value } # => [:baz, 2]
    [].min_by {|element| -element }                        # => nil

With a block given and positive integer argument `n` given, returns an array containing the `n` elements for which the block returns minimum values:

    (1..4).min_by(2) {|element| -element }
    # => [4, 3]
    %w[a b c d].min_by(2) {|element| -element.ord }
    # => ["d", "c"]
    {foo: 0, bar: 1, baz: 2}.min_by(2) {|key, value| -value }
    # => [[:baz, 2], [:bar, 1]]
    [].min_by(2) {|element| -element }
    # => []

Returns an `Enumerator` if no block is given.

Related: `min`, `minmax`, `max_by`.

    static VALUE
    enum_min_by(int argc, VALUE *argv, VALUE obj)
    {
        struct MEMO *memo;
        VALUE num;

        rb_check_arity(argc, 0, 1);

        RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);

        if (argc && !NIL_P(num = argv[0]))
            return rb_nmin_run(obj, num, 1, 0, 0);

        memo = MEMO_NEW(Qundef, Qnil, 0);
        rb_block_call(obj, id_each, 0, 0, min_by_i, (VALUE)memo);
        return memo->v2;
    }

minmax → [minimum, maximum] click to toggle source
minmax {|a, b| ... } → [minimum, maximum]

Returns a 2-element array containing the minimum and maximum elements according to a given criterion. The ordering of equal elements is indeterminate and may be unstable.

With no argument and no block, returns the minimum and maximum elements, using the elements’ own method `<=>` for comparison:

    (1..4).minmax                   # => [1, 4]
    (-4..-1).minmax                 # => [-4, -1]
    %w[d c b a].minmax              # => ["a", "d"]
    {foo: 0, bar: 1, baz: 2}.minmax # => [[:bar, 1], [:foo, 0]]
    [].minmax                       # => [nil, nil]

With a block given, returns the minimum and maximum elements as determined by the block:

    %w[xxx x xxxx xx].minmax {|a, b| a.size <=> b.size } # => ["x", "xxxx"]
    h = {foo: 0, bar: 1, baz: 2}
    h.minmax {|pair1, pair2| pair1[1] <=> pair2[1] }
    # => [[:foo, 0], [:baz, 2]]
    [].minmax {|a, b| a <=> b }                          # => [nil, nil]

Related: `min`, `max`, `minmax_by`.

    static VALUE
    enum_minmax(VALUE obj)
    {
        VALUE memo;
        struct minmax_t *m = NEW_MEMO_FOR(struct minmax_t, memo);

        m->min = Qundef;
        m->last = Qundef;
        if (rb_block_given_p()) {
            rb_block_call(obj, id_each, 0, 0, minmax_ii, memo);
            if (!UNDEF_P(m->last))
                minmax_ii_update(m->last, m->last, m);
        }
        else {
            rb_block_call(obj, id_each, 0, 0, minmax_i, memo);
            if (!UNDEF_P(m->last))
                minmax_i_update(m->last, m->last, m);
        }
        if (!UNDEF_P(m->min)) {
            return rb_assoc_new(m->min, m->max);
        }
        return rb_assoc_new(Qnil, Qnil);
    }

minmax_by {|element| ... } → [minimum, maximum] click to toggle source
minmax_by → enumerator

Returns a 2-element array containing the elements for which the block returns minimum and maximum values:

    (1..4).minmax_by {|element| -element }
    # => [4, 1]
    %w[a b c d].minmax_by {|element| -element.ord }
    # => ["d", "a"]
    {foo: 0, bar: 1, baz: 2}.minmax_by {|key, value| -value }
    # => [[:baz, 2], [:foo, 0]]
    [].minmax_by {|element| -element }
    # => [nil, nil]

Returns an `Enumerator` if no block is given.

Related: `max_by`, `minmax`, `min_by`.

    static VALUE
    enum_minmax_by(VALUE obj)
    {
        VALUE memo;
        struct minmax_by_t *m = NEW_MEMO_FOR(struct minmax_by_t, memo);

        RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);

        m->min_bv = Qundef;
        m->max_bv = Qundef;
        m->min = Qnil;
        m->max = Qnil;
        m->last_bv = Qundef;
        m->last = Qundef;
        rb_block_call(obj, id_each, 0, 0, minmax_by_i, memo);
        if (!UNDEF_P(m->last_bv))
            minmax_by_i_update(m->last_bv, m->last_bv, m->last, m->last, m);
        m = MEMO_FOR(struct minmax_by_t, memo);
        return rb_assoc_new(m->min, m->max);
    }

none? → true or false click to toggle source
none?(pattern) → true or false
none? {|element| ... } → true or false

Returns whether no element meets a given criterion.

With no argument and no block, returns whether no element is truthy:

    (1..4).none?           # => false
    [nil, false].none?     # => true
    {foo: 0}.none?         # => false
    {foo: 0, bar: 1}.none? # => false
    [].none?               # => true

With argument `pattern` and no block, returns whether for no element `element`, `pattern === element`:

    [nil, false, 1.1].none?(Integer)      # => true
    %w[bar baz bat bam].none?(/m/)        # => false
    %w[bar baz bat bam].none?(/foo/)      # => true
    %w[bar baz bat bam].none?('ba')       # => true
    {foo: 0, bar: 1, baz: 2}.none?(Hash)  # => true
    {foo: 0}.none?(Array)                 # => false
    [].none?(Integer)                     # => true

With a block given, returns whether the block returns a truthy value for no element:

    (1..4).none? {|element| element < 1 }                     # => true
    (1..4).none? {|element| element < 2 }                     # => false
    {foo: 0, bar: 1, baz: 2}.none? {|key, value| value < 0 }  # => true
    {foo: 0, bar: 1, baz: 2}.none? {|key, value| value < 1 } # => false

Related: `one?`, `all?`, `any?`.

    static VALUE
    enum_none(int argc, VALUE *argv, VALUE obj)
    {
        struct MEMO *memo = MEMO_ENUM_NEW(Qtrue);

        WARN_UNUSED_BLOCK(argc);
        rb_block_call(obj, id_each, 0, 0, ENUMFUNC(none), (VALUE)memo);
        return memo->v1;
    }

one? → true or false click to toggle source
one?(pattern) → true or false
one? {|element| ... } → true or false

Returns whether exactly one element meets a given criterion.

With no argument and no block, returns whether exactly one element is truthy:

    (1..1).one?           # => true
    [1, nil, false].one?  # => true
    (1..4).one?           # => false
    {foo: 0}.one?         # => true
    {foo: 0, bar: 1}.one? # => false
    [].one?               # => false

With argument `pattern` and no block, returns whether for exactly one element `element`, `pattern === element`:

    [nil, false, 0].one?(Integer)        # => true
    [nil, false, 0].one?(Numeric)        # => true
    [nil, false, 0].one?(Float)          # => false
    %w[bar baz bat bam].one?(/m/)        # => true
    %w[bar baz bat bam].one?(/foo/)      # => false
    %w[bar baz bat bam].one?('ba')       # => false
    {foo: 0, bar: 1, baz: 2}.one?(Array) # => false
    {foo: 0}.one?(Array)                 # => true
    [].one?(Integer)                     # => false

With a block given, returns whether the block returns a truthy value for exactly one element:

    (1..4).one? {|element| element < 2 }                     # => true
    (1..4).one? {|element| element < 1 }                     # => false
    {foo: 0, bar: 1, baz: 2}.one? {|key, value| value < 1 }  # => true
    {foo: 0, bar: 1, baz: 2}.one? {|key, value| value < 2 } # => false

Related: `none?`, `all?`, `any?`.

    static VALUE
    enum_one(int argc, VALUE *argv, VALUE obj)
    {
        struct MEMO *memo = MEMO_ENUM_NEW(Qundef);
        VALUE result;

        WARN_UNUSED_BLOCK(argc);
        rb_block_call(obj, id_each, 0, 0, ENUMFUNC(one), (VALUE)memo);
        result = memo->v1;
        if (UNDEF_P(result)) return Qfalse;
        return result;
    }

partition {|element| ... } → [true_array, false_array] click to toggle source
partition → enumerator

With a block given, returns an array of two arrays:

- The first having those elements for which the block returns a truthy value.

- The other having all other elements.

Examples:

    p = (1..4).partition {|i| i.even? }
    p # => [[2, 4], [1, 3]]
    p = ('a'..'d').partition {|c| c < 'c' }
    p # => [["a", "b"], ["c", "d"]]
    h = {foo: 0, bar: 1, baz: 2, bat: 3}
    p = h.partition {|key, value| key.start_with?('b') }
    p # => [[[:bar, 1], [:baz, 2], [:bat, 3]], [[:foo, 0]]]
    p = h.partition {|key, value| value < 2 }
    p # => [[[:foo, 0], [:bar, 1]], [[:baz, 2], [:bat, 3]]]

With no block given, returns an `Enumerator`.

Related: `Enumerable#group_by`.

    static VALUE
    enum_partition(VALUE obj)
    {
        struct MEMO *memo;

        RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);

        memo = MEMO_NEW(rb_ary_new(), rb_ary_new(), 0);
        rb_block_call(obj, id_each, 0, 0, partition_i, (VALUE)memo);

        return rb_assoc_new(memo->v1, memo->v2);
    }

reduce
Alias for: inject
reject {|element| ... } → array click to toggle source
reject → enumerator

Returns an array of objects rejected by the block.

With a block given, calls the block with successive elements; returns an array of those elements for which the block returns `nil` or `false`:

    (0..9).reject {|i| i * 2 if i.even? }                             # => [1, 3, 5, 7, 9]
    {foo: 0, bar: 1, baz: 2}.reject {|key, value| key if value.odd? } # => {:foo=>0, :baz=>2}

When no block given, returns an `Enumerator`.

Related: `select`.

    static VALUE
    enum_reject(VALUE obj)
    {
        VALUE ary;

        RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);

        ary = rb_ary_new();
        rb_block_call(obj, id_each, 0, 0, reject_i, ary);

        return ary;
    }

reverse_each(*args) {|element| ... } → self click to toggle source
reverse_each(*args) → enumerator

With a block given, calls the block with each element, but in reverse order; returns `self`:

    a = []
    (1..4).reverse_each {|element| a.push(-element) } # => 1..4
    a # => [-4, -3, -2, -1]

    a = []
    %w[a b c d].reverse_each {|element| a.push(element) }
    # => ["a", "b", "c", "d"]
    a # => ["d", "c", "b", "a"]

    a = []
    h.reverse_each {|element| a.push(element) }
    # => {:foo=>0, :bar=>1, :baz=>2}
    a # => [[:baz, 2], [:bar, 1], [:foo, 0]]

With no block given, returns an `Enumerator`.

    static VALUE
    enum_reverse_each(int argc, VALUE *argv, VALUE obj)
    {
        VALUE ary;
        long len;

        RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);

        ary = enum_to_a(argc, argv, obj);

        len = RARRAY_LEN(ary);
        while (len--) {
            long nlen;
            rb_yield(RARRAY_AREF(ary, len));
            nlen = RARRAY_LEN(ary);
            if (nlen < len) {
                len = nlen;
            }
        }

        return obj;
    }

select {|element| ... } → array
select → enumerator

Returns an array containing elements selected by the block.

With a block given, calls the block with successive elements; returns an array of those elements for which the block returns a truthy value:

    (0..9).select {|element| element % 3 == 0 } # => [0, 3, 6, 9]
    a = {foo: 0, bar: 1, baz: 2}.select {|key, value| key.start_with?('b') }
    a # => {:bar=>1, :baz=>2}

With no block given, returns an `Enumerator`.

Related: `reject`.

Alias for: find_all
slice_after(pattern) → an_enumerator click to toggle source
slice_after { |elt| bool } → an_enumerator

Creates an enumerator for each chunked elements. The ends of chunks are defined by pattern and the block.

If `pattern === elt` returns `true` or the block returns `true` for the element, the element is end of a chunk.

The `===` and block is called from the first element to the last element of enum.

The result enumerator yields the chunked elements as an array. So `each` method can be called as follows:

    enum.slice_after(pattern).each { |ary| ... }
    enum.slice_after { |elt| bool }.each { |ary| ... }

Other methods of the `Enumerator` class and `Enumerable` module, such as `map`, etc., are also usable.

For example, continuation lines (lines end with backslash) can be concatenated as follows:

    lines = ["foo\n", "bar\\\n", "baz\n", "\n", "qux\n"]
    e = lines.slice_after(/(?<!\\)\n\z/)
    p e.to_a
    #=> [["foo\n"], ["bar\\\n", "baz\n"], ["\n"], ["qux\n"]]
    p e.map {|ll| ll[0...-1].map {|l| l.sub(/\\\n\z/, "") }.join + ll.last }
    #=>["foo\n", "barbaz\n", "\n", "qux\n"]

    static VALUE
    enum_slice_after(int argc, VALUE *argv, VALUE enumerable)
    {
        VALUE enumerator;
        VALUE pat = Qnil, pred = Qnil;

        if (rb_block_given_p()) {
            if (0 < argc)
                rb_raise(rb_eArgError, "both pattern and block are given");
            pred = rb_block_proc();
        }
        else {
            rb_scan_args(argc, argv, "1", &pat);
        }

        enumerator = rb_obj_alloc(rb_cEnumerator);
        rb_ivar_set(enumerator, id_sliceafter_enum, enumerable);
        rb_ivar_set(enumerator, id_sliceafter_pat, pat);
        rb_ivar_set(enumerator, id_sliceafter_pred, pred);

        rb_block_call(enumerator, idInitialize, 0, 0, sliceafter_i, enumerator);
        return enumerator;
    }

slice_before(pattern) → enumerator click to toggle source
slice_before {|elt| ... } → enumerator

With argument `pattern`, returns an enumerator that uses the pattern to partition elements into arrays (“slices”). An element begins a new slice if `element === pattern` (or if it is the first element).

    a = %w[foo bar fop for baz fob fog bam foy]
    e = a.slice_before(/ba/) # => #<Enumerator: ...>
    e.each {|array| p array }

Output:

    ["foo"]
    ["bar", "fop", "for"]
    ["baz", "fob", "fog"]
    ["bam", "foy"]

With a block, returns an enumerator that uses the block to partition elements into arrays. An element begins a new slice if its block return is a truthy value (or if it is the first element):

    e = (1..20).slice_before {|i| i % 4 == 2 } # => #<Enumerator: ...>
    e.each {|array| p array }

Output:

    [1]
    [2, 3, 4, 5]
    [6, 7, 8, 9]
    [10, 11, 12, 13]
    [14, 15, 16, 17]
    [18, 19, 20]

Other methods of the `Enumerator` class and `Enumerable` module, such as `to_a`, `map`, etc., are also usable.

For example, iteration over ChangeLog entries can be implemented as follows:

    # iterate over ChangeLog entries.
    open("ChangeLog") { |f|
      f.slice_before(/\A\S/).each { |e| pp e }
    }

    # same as above.  block is used instead of pattern argument.
    open("ChangeLog") { |f|
      f.slice_before { |line| /\A\S/ === line }.each { |e| pp e }
    }

“svn proplist -R” produces multiline output for each file. They can be chunked as follows:

    IO.popen([{"LC_ALL"=>"C"}, "svn", "proplist", "-R"]) { |f|
      f.lines.slice_before(/\AProp/).each { |lines| p lines }
    }
    #=> ["Properties on '.':\n", "  svn:ignore\n", "  svk:merge\n"]
    #   ["Properties on 'goruby.c':\n", "  svn:eol-style\n"]
    #   ["Properties on 'complex.c':\n", "  svn:mime-type\n", "  svn:eol-style\n"]
    #   ["Properties on 'regparse.c':\n", "  svn:eol-style\n"]
    #   ...

If the block needs to maintain state over multiple elements, local variables can be used. For example, three or more consecutive increasing numbers can be squashed as follows (see `chunk_while` for a better way):

    a = [0, 2, 3, 4, 6, 7, 9]
    prev = a[0]
    p a.slice_before { |e|
      prev, prev2 = e, prev
      prev2 + 1 != e
    }.map { |es|
      es.length <= 2 ? es.join(",") : "#{es.first}-#{es.last}"
    }.join(",")
    #=> "0,2-4,6,7,9"

However local variables should be used carefully if the result enumerator is enumerated twice or more. The local variables should be initialized for each enumeration. `Enumerator.new` can be used to do it.

    # Word wrapping.  This assumes all characters have same width.
    def wordwrap(words, maxwidth)
      Enumerator.new {|y|
        # cols is initialized in Enumerator.new.
        cols = 0
        words.slice_before { |w|
          cols += 1 if cols != 0
          cols += w.length
          if maxwidth < cols
            cols = w.length
            true
          else
            false
          end
        }.each {|ws| y.yield ws }
      }
    end
    text = (1..20).to_a.join(" ")
    enum = wordwrap(text.split(/\s+/), 10)
    puts "-"*10
    enum.each { |ws| puts ws.join(" ") } # first enumeration.
    puts "-"*10
    enum.each { |ws| puts ws.join(" ") } # second enumeration generates same result as the first.
    puts "-"*10
    #=> ----------
    #   1 2 3 4 5
    #   6 7 8 9 10
    #   11 12 13
    #   14 15 16
    #   17 18 19
    #   20
    #   ----------
    #   1 2 3 4 5
    #   6 7 8 9 10
    #   11 12 13
    #   14 15 16
    #   17 18 19
    #   20
    #   ----------

mbox contains series of mails which start with Unix From line. So each mail can be extracted by slice before Unix From line.

    # parse mbox
    open("mbox") { |f|
      f.slice_before { |line|
        line.start_with? "From "
      }.each { |mail|
        unix_from = mail.shift
        i = mail.index("\n")
        header = mail[0...i]
        body = mail[(i+1)..-1]
        body.pop if body.last == "\n"
        fields = header.slice_before { |line| !" \t".include?(line[0]) }.to_a
        p unix_from
        pp fields
        pp body
      }
    }

    # split mails in mbox (slice before Unix From line after an empty line)
    open("mbox") { |f|
      emp = true
      f.slice_before { |line|
        prevemp = emp
        emp = line == "\n"
        prevemp && line.start_with?("From ")
      }.each { |mail|
        mail.pop if mail.last == "\n"
        pp mail
      }
    }

    static VALUE
    enum_slice_before(int argc, VALUE *argv, VALUE enumerable)
    {
        VALUE enumerator;

        if (rb_block_given_p()) {
            if (argc != 0)
                rb_error_arity(argc, 0, 0);
            enumerator = rb_obj_alloc(rb_cEnumerator);
            rb_ivar_set(enumerator, id_slicebefore_sep_pred, rb_block_proc());
        }
        else {
            VALUE sep_pat;
            rb_scan_args(argc, argv, "1", &sep_pat);
            enumerator = rb_obj_alloc(rb_cEnumerator);
            rb_ivar_set(enumerator, id_slicebefore_sep_pat, sep_pat);
        }
        rb_ivar_set(enumerator, id_slicebefore_enumerable, enumerable);
        rb_block_call(enumerator, idInitialize, 0, 0, slicebefore_i, enumerator);
        return enumerator;
    }

slice_when {|elt_before, elt_after| bool } → an_enumerator click to toggle source

Creates an enumerator for each chunked elements. The beginnings of chunks are defined by the block.

This method splits each chunk using adjacent elements, elt_before and elt_after, in the receiver enumerator. This method split chunks between elt_before and elt_after where the block returns `true`.

The block is called the length of the receiver enumerator minus one.

The result enumerator yields the chunked elements as an array. So `each` method can be called as follows:

    enum.slice_when { |elt_before, elt_after| bool }.each { |ary| ... }

Other methods of the `Enumerator` class and `Enumerable` module, such as `to_a`, `map`, etc., are also usable.

For example, one-by-one increasing subsequence can be chunked as follows:

    a = [1,2,4,9,10,11,12,15,16,19,20,21]
    b = a.slice_when {|i, j| i+1 != j }
    p b.to_a #=> [[1, 2], [4], [9, 10, 11, 12], [15, 16], [19, 20, 21]]
    c = b.map {|a| a.length < 3 ? a : "#{a.first}-#{a.last}" }
    p c #=> [[1, 2], [4], "9-12", [15, 16], "19-21"]
    d = c.join(",")
    p d #=> "1,2,4,9-12,15,16,19-21"

Near elements (threshold: 6) in sorted array can be chunked as follows:

    a = [3, 11, 14, 25, 28, 29, 29, 41, 55, 57]
    p a.slice_when {|i, j| 6 < j - i }.to_a
    #=> [[3], [11, 14], [25, 28, 29, 29], [41], [55, 57]]

Increasing (non-decreasing) subsequence can be chunked as follows:

    a = [0, 9, 2, 2, 3, 2, 7, 5, 9, 5]
    p a.slice_when {|i, j| i > j }.to_a
    #=> [[0, 9], [2, 2, 3], [2, 7], [5, 9], [5]]

Adjacent evens and odds can be chunked as follows: (`Enumerable#chunk` is another way to do it.)

    a = [7, 5, 9, 2, 0, 7, 9, 4, 2, 0]
    p a.slice_when {|i, j| i.even? != j.even? }.to_a
    #=> [[7, 5, 9], [2, 0], [7, 9], [4, 2, 0]]

Paragraphs (non-empty lines with trailing empty lines) can be chunked as follows: (See `Enumerable#chunk` to ignore empty lines.)

    lines = ["foo\n", "bar\n", "\n", "baz\n", "qux\n"]
    p lines.slice_when {|l1, l2| /\A\s*\z/ =~ l1 && /\S/ =~ l2 }.to_a
    #=> [["foo\n", "bar\n", "\n"], ["baz\n", "qux\n"]]

`Enumerable#chunk_while` does the same, except splitting when the block returns `false` instead of `true`.

    static VALUE
    enum_slice_when(VALUE enumerable)
    {
        VALUE enumerator;
        VALUE pred;

        pred = rb_block_proc();

        enumerator = rb_obj_alloc(rb_cEnumerator);
        rb_ivar_set(enumerator, id_slicewhen_enum, enumerable);
        rb_ivar_set(enumerator, id_slicewhen_pred, pred);
        rb_ivar_set(enumerator, id_slicewhen_inverted, Qfalse);

        rb_block_call(enumerator, idInitialize, 0, 0, slicewhen_i, enumerator);
        return enumerator;
    }

sort → array click to toggle source
sort {|a, b| ... } → array

Returns an array containing the sorted elements of `self`. The ordering of equal elements is indeterminate and may be unstable.

With no block given, the sort compares using the elements’ own method `<=>`:

    %w[b c a d].sort              # => ["a", "b", "c", "d"]
    {foo: 0, bar: 1, baz: 2}.sort # => [[:bar, 1], [:baz, 2], [:foo, 0]]

With a block given, comparisons in the block determine the ordering. The block is called with two elements `a` and `b`, and must return:

- A negative integer if `a < b`.

- Zero if `a == b`.

- A positive integer if `a > b`.

Examples:

    a = %w[b c a d]
    a.sort {|a, b| b <=> a } # => ["d", "c", "b", "a"]
    h = {foo: 0, bar: 1, baz: 2}
    h.sort {|a, b| b <=> a } # => [[:foo, 0], [:baz, 2], [:bar, 1]]

See also `sort_by`. It implements a Schwartzian transform which is useful when key computation or comparison is expensive.

    static VALUE
    enum_sort(VALUE obj)
    {
        return rb_ary_sort_bang(enum_to_a(0, 0, obj));
    }

sort_by {|element| ... } → array click to toggle source
sort_by → enumerator

With a block given, returns an array of elements of `self`, sorted according to the value returned by the block for each element. The ordering of equal elements is indeterminate and may be unstable.

Examples:

    a = %w[xx xxx x xxxx]
    a.sort_by {|s| s.size }        # => ["x", "xx", "xxx", "xxxx"]
    a.sort_by {|s| -s.size }       # => ["xxxx", "xxx", "xx", "x"]
    h = {foo: 2, bar: 1, baz: 0}
    h.sort_by{|key, value| value } # => [[:baz, 0], [:bar, 1], [:foo, 2]]
    h.sort_by{|key, value| key }   # => [[:bar, 1], [:baz, 0], [:foo, 2]]

With no block given, returns an `Enumerator`.

The current implementation of `sort_by` generates an array of tuples containing the original collection element and the mapped value. This makes `sort_by` fairly expensive when the keysets are simple.

    require 'benchmark'

    a = (1..100000).map { rand(100000) }

    Benchmark.bm(10) do |b|
      b.report("Sort")    { a.sort }
      b.report("Sort by") { a.sort_by { |a| a } }
    end

produces:

    user     system      total        real
    Sort        0.180000   0.000000   0.180000 (  0.175469)
    Sort by     1.980000   0.040000   2.020000 (  2.013586)

However, consider the case where comparing the keys is a non-trivial operation. The following code sorts some files on modification time using the basic `sort` method.

    files = Dir["*"]
    sorted = files.sort { |a, b| File.new(a).mtime <=> File.new(b).mtime }
    sorted   #=> ["mon", "tues", "wed", "thurs"]

This sort is inefficient: it generates two new `File` objects during every comparison. A slightly better technique is to use the `Kernel#test` method to generate the modification times directly.

    files = Dir["*"]
    sorted = files.sort { |a, b|
      test(?M, a) <=> test(?M, b)
    }
    sorted   #=> ["mon", "tues", "wed", "thurs"]

This still generates many unnecessary `Time` objects. A more efficient technique is to cache the sort keys (modification times in this case) before the sort. Perl users often call this approach a Schwartzian transform, after Randal Schwartz. We construct a temporary array, where each element is an array containing our sort key along with the filename. We sort this array, and then extract the filename from the result.

    sorted = Dir["*"].collect { |f|
       [test(?M, f), f]
    }.sort.collect { |f| f[1] }
    sorted   #=> ["mon", "tues", "wed", "thurs"]

This is exactly what `sort_by` does internally.

    sorted = Dir["*"].sort_by { |f| test(?M, f) }
    sorted   #=> ["mon", "tues", "wed", "thurs"]

To produce the reverse of a specific order, the following can be used:

    ary.sort_by { ... }.reverse!

    static VALUE
    enum_sort_by(VALUE obj)
    {
        VALUE ary, buf;
        struct MEMO *memo;
        long i;
        struct sort_by_data *data;

        RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);

        if (RB_TYPE_P(obj, T_ARRAY) && RARRAY_LEN(obj) <= LONG_MAX/2) {
            ary = rb_ary_new2(RARRAY_LEN(obj)*2);
        }
        else {
            ary = rb_ary_new();
        }
        RBASIC_CLEAR_CLASS(ary);
        buf = rb_ary_hidden_new(SORT_BY_BUFSIZE*2);
        rb_ary_store(buf, SORT_BY_BUFSIZE*2-1, Qnil);
        memo = MEMO_NEW(0, 0, 0);
        data = (struct sort_by_data *)&memo->v1;
        RB_OBJ_WRITE(memo, &data->ary, ary);
        RB_OBJ_WRITE(memo, &data->buf, buf);
        data->n = 0;
        data->primitive_uniformed = SORT_BY_UNIFORMED((CMP_OPTIMIZABLE(FLOAT) && CMP_OPTIMIZABLE(INTEGER)),
                                                      CMP_OPTIMIZABLE(FLOAT),
                                                      CMP_OPTIMIZABLE(INTEGER));
        rb_block_call(obj, id_each, 0, 0, sort_by_i, (VALUE)memo);
        ary = data->ary;
        buf = data->buf;
        if (data->n) {
            rb_ary_resize(buf, data->n*2);
            rb_ary_concat(ary, buf);
        }
        if (RARRAY_LEN(ary) > 2) {
            if (data->primitive_uniformed) {
                RARRAY_PTR_USE(ary, ptr,
                               rb_uniform_intro_sort_2((struct rb_uniform_sort_data*)ptr,
                                                       (struct rb_uniform_sort_data*)(ptr + RARRAY_LEN(ary))));
            }
            else {
                RARRAY_PTR_USE(ary, ptr,
                               ruby_qsort(ptr, RARRAY_LEN(ary)/2, 2*sizeof(VALUE),
                                          sort_by_cmp, (void *)ary));
            }
        }
        if (RBASIC(ary)->klass) {
            rb_raise(rb_eRuntimeError, "sort_by reentered");
        }
        for (i=1; i<RARRAY_LEN(ary); i+=2) {
            RARRAY_ASET(ary, i/2, RARRAY_AREF(ary, i));
        }
        rb_ary_resize(ary, RARRAY_LEN(ary)/2);
        RBASIC_SET_CLASS_RAW(ary, rb_cArray);

        return ary;
    }

sum(initial_value = 0) → number click to toggle source
sum(initial_value = 0) {|element| ... } → object

With no block given, returns the sum of `initial_value` and the elements:

    (1..100).sum          # => 5050
    (1..100).sum(1)       # => 5051
    ('a'..'d').sum('foo') # => "fooabcd"

Generally, the sum is computed using methods `+` and `each`; for performance optimizations, those methods may not be used, and so any redefinition of those methods may not have effect here.

One such optimization: When possible, computes using Gauss’s summation formula n(n+1)/2:

    100 * (100 + 1) / 2 # => 5050

With a block given, calls the block with each element; returns the sum of `initial_value` and the block return values:

    (1..4).sum {|i| i*i }                        # => 30
    (1..4).sum(100) {|i| i*i }                   # => 130
    h = {a: 0, b: 1, c: 2, d: 3, e: 4, f: 5}
    h.sum {|key, value| value.odd? ? value : 0 } # => 9
    ('a'..'f').sum('x') {|c| c < 'd' ? c : '' }  # => "xabc"

    static VALUE
    enum_sum(int argc, VALUE* argv, VALUE obj)
    {
        struct enum_sum_memo memo;
        VALUE beg, end;
        int excl;

        memo.v = (rb_check_arity(argc, 0, 1) == 0) ? LONG2FIX(0) : argv[0];
        memo.block_given = rb_block_given_p();
        memo.n = 0;
        memo.r = Qundef;

        if ((memo.float_value = RB_FLOAT_TYPE_P(memo.v))) {
            memo.f = RFLOAT_VALUE(memo.v);
            memo.c = 0.0;
        }
        else {
            memo.f = 0.0;
            memo.c = 0.0;
        }

        if (RTEST(rb_range_values(obj, &beg, &end, &excl))) {
            if (!memo.block_given && !memo.float_value &&
                    (FIXNUM_P(beg) || RB_BIGNUM_TYPE_P(beg)) &&
                    (FIXNUM_P(end) || RB_BIGNUM_TYPE_P(end))) {
                return int_range_sum(beg, end, excl, memo.v);
            }
        }

        if (RB_TYPE_P(obj, T_HASH) &&
                rb_method_basic_definition_p(CLASS_OF(obj), id_each))
            hash_sum(obj, &memo);
        else
            rb_block_call(obj, id_each, 0, 0, enum_sum_i, (VALUE)&memo);

        if (memo.float_value) {
            return DBL2NUM(memo.f + memo.c);
        }
        else {
            if (memo.n != 0)
                memo.v = rb_fix_plus(LONG2FIX(memo.n), memo.v);
            if (!UNDEF_P(memo.r)) {
                memo.v = rb_rational_plus(memo.r, memo.v);
            }
            return memo.v;
        }
    }

take(n) → array click to toggle source

For non-negative integer `n`, returns the first `n` elements:

    r = (1..4)
    r.take(2) # => [1, 2]
    r.take(0) # => []

    h = {foo: 0, bar: 1, baz: 2, bat: 3}
    h.take(2) # => [[:foo, 0], [:bar, 1]]

    static VALUE
    enum_take(VALUE obj, VALUE n)
    {
        struct MEMO *memo;
        VALUE result;
        long len = NUM2LONG(n);

        if (len < 0) {
            rb_raise(rb_eArgError, "attempt to take negative size");
        }

        if (len == 0) return rb_ary_new2(0);
        result = rb_ary_new2(len);
        memo = MEMO_NEW(result, 0, len);
        rb_block_call(obj, id_each, 0, 0, take_i, (VALUE)memo);
        return result;
    }

take_while {|element| ... } → array click to toggle source
take_while → enumerator

Calls the block with successive elements as long as the block returns a truthy value; returns an array of all elements up to that point:

    (1..4).take_while{|i| i < 3 } # => [1, 2]
    h = {foo: 0, bar: 1, baz: 2}
    h.take_while{|element| key, value = *element; value < 2 }
    # => [[:foo, 0], [:bar, 1]]

With no block given, returns an `Enumerator`.

    static VALUE
    enum_take_while(VALUE obj)
    {
        VALUE ary;

        RETURN_ENUMERATOR(obj, 0, 0);
        ary = rb_ary_new();
        rb_block_call(obj, id_each, 0, 0, take_while_i, ary);
        return ary;
    }

tally → new_hash click to toggle source
tally(hash) → hash

Returns a hash containing the counts of equal elements:

- Each key is an element of `self`.

- Each value is the number elements equal to that key.

With no argument:

    %w[a b c b c a c b].tally # => {"a"=>2, "b"=>3, "c"=>3}

With a hash argument, that hash is used for the tally (instead of a new hash), and is returned; this may be useful for accumulating tallies across multiple enumerables:

    hash = {}
    hash = %w[a c d b c a].tally(hash)
    hash # => {"a"=>2, "c"=>2, "d"=>1, "b"=>1}
    hash = %w[b a z].tally(hash)
    hash # => {"a"=>3, "c"=>2, "d"=>1, "b"=>2, "z"=>1}
    hash = %w[b a m].tally(hash)
    hash # => {"a"=>4, "c"=>2, "d"=>1, "b"=>3, "z"=>1, "m"=> 1}

    static VALUE
    enum_tally(int argc, VALUE *argv, VALUE obj)
    {
        VALUE hash;
        if (rb_check_arity(argc, 0, 1)) {
            hash = rb_to_hash_type(argv[0]);
            rb_check_frozen(hash);
        }
        else {
            hash = rb_hash_new();
        }

        return enum_hashify_into(obj, 0, 0, tally_i, hash);
    }

to_a(*args) → array click to toggle source

Returns an array containing the items in `self`:

    (0..4).to_a # => [0, 1, 2, 3, 4]

    static VALUE
    enum_to_a(int argc, VALUE *argv, VALUE obj)
    {
        VALUE ary = rb_ary_new();

        rb_block_call_kw(obj, id_each, argc, argv, collect_all, ary, RB_PASS_CALLED_KEYWORDS);

        return ary;
    }

Also aliased as: entries
to_h(*args) → hash click to toggle source
to_h(*args) {|element| ... } → hash

When `self` consists of 2-element arrays, returns a hash each of whose entries is the key-value pair formed from one of those arrays:

    [[:foo, 0], [:bar, 1], [:baz, 2]].to_h # => {:foo=>0, :bar=>1, :baz=>2}

When a block is given, the block is called with each element of `self`; the block should return a 2-element array which becomes a key-value pair in the returned hash:

    (0..3).to_h {|i| [i, i ** 2]} # => {0=>0, 1=>1, 2=>4, 3=>9}

Raises an exception if an element of `self` is not a 2-element array, and a block is not passed.

    static VALUE
    enum_to_h(int argc, VALUE *argv, VALUE obj)
    {
        rb_block_call_func *iter = rb_block_given_p() ? enum_to_h_ii : enum_to_h_i;
        return enum_hashify(obj, argc, argv, iter);
    }

to_set(klass = Set, *args, &block) click to toggle source

Makes a set from the enumerable object with given arguments. Needs to `require "set"` to use this method.

    # File lib/set.rb, line 847
    def to_set(klass = Set, *args, &block)
      klass.new(self, *args, &block)
    end

uniq → array click to toggle source
uniq {|element| ... } → array

With no block, returns a new array containing only unique elements; the array has no two elements `e0` and `e1` such that `e0.eql?(e1)`:

    %w[a b c c b a a b c].uniq       # => ["a", "b", "c"]
    [0, 1, 2, 2, 1, 0, 0, 1, 2].uniq # => [0, 1, 2]

With a block, returns a new array containing elements only for which the block returns a unique value:

    a = [0, 1, 2, 3, 4, 5, 5, 4, 3, 2, 1]
    a.uniq {|i| i.even? ? i : 0 } # => [0, 2, 4]
    a = %w[a b c d e e d c b a a b c d e]
    a.uniq {|c| c < 'c' }         # => ["a", "c"]

    static VALUE
    enum_uniq(VALUE obj)
    {
        VALUE hash, ret;
        rb_block_call_func *const func =
            rb_block_given_p() ? uniq_iter : uniq_func;

        hash = rb_obj_hide(rb_hash_new());
        rb_block_call(obj, id_each, 0, 0, func, hash);
        ret = rb_hash_values(hash);
        rb_hash_clear(hash);
        return ret;
    }

zip(*other_enums) → array click to toggle source
zip(*other_enums) {|array| ... } → nil

With no block given, returns a new array `new_array` of size self.size whose elements are arrays. Each nested array `new_array[n]` is of size `other_enums.size+1`, and contains:

- The `n`-th element of self.

- The `n`-th element of each of the `other_enums`.

If all `other_enums` and self are the same size, all elements are included in the result, and there is no `nil`-filling:

    a = [:a0, :a1, :a2, :a3]
    b = [:b0, :b1, :b2, :b3]
    c = [:c0, :c1, :c2, :c3]
    d = a.zip(b, c)
    d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]

    f = {foo: 0, bar: 1, baz: 2}
    g = {goo: 3, gar: 4, gaz: 5}
    h = {hoo: 6, har: 7, haz: 8}
    d = f.zip(g, h)
    d # => [
      #      [[:foo, 0], [:goo, 3], [:hoo, 6]],
      #      [[:bar, 1], [:gar, 4], [:har, 7]],
      #      [[:baz, 2], [:gaz, 5], [:haz, 8]]
      #    ]

If any enumerable in other_enums is smaller than self, fills to `self.size` with `nil`:

    a = [:a0, :a1, :a2, :a3]
    b = [:b0, :b1, :b2]
    c = [:c0, :c1]
    d = a.zip(b, c)
    d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, nil], [:a3, nil, nil]]

If any enumerable in other_enums is larger than self, its trailing elements are ignored:

    a = [:a0, :a1, :a2, :a3]
    b = [:b0, :b1, :b2, :b3, :b4]
    c = [:c0, :c1, :c2, :c3, :c4, :c5]
    d = a.zip(b, c)
    d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]

When a block is given, calls the block with each of the sub-arrays (formed as above); returns nil:

    a = [:a0, :a1, :a2, :a3]
    b = [:b0, :b1, :b2, :b3]
    c = [:c0, :c1, :c2, :c3]
    a.zip(b, c) {|sub_array| p sub_array} # => nil

Output:

    [:a0, :b0, :c0]
    [:a1, :b1, :c1]
    [:a2, :b2, :c2]
    [:a3, :b3, :c3]

    static VALUE
    enum_zip(int argc, VALUE *argv, VALUE obj)
    {
        int i;
        ID conv;
        struct MEMO *memo;
        VALUE result = Qnil;
        VALUE args = rb_ary_new4(argc, argv);
        int allary = TRUE;

        argv = RARRAY_PTR(args);
        for (i=0; i<argc; i++) {
            VALUE ary = rb_check_array_type(argv[i]);
            if (NIL_P(ary)) {
                allary = FALSE;
                break;
            }
            argv[i] = ary;
        }
        if (!allary) {
            static const VALUE sym_each = STATIC_ID2SYM(id_each);
            CONST_ID(conv, "to_enum");
            for (i=0; i<argc; i++) {
                if (!rb_respond_to(argv[i], id_each)) {
                    rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (must respond to :each)",
                             rb_obj_class(argv[i]));
                }
                argv[i] = rb_funcallv(argv[i], conv, 1, &sym_each);
            }
        }
        if (!rb_block_given_p()) {
            result = rb_ary_new();
        }

        /* TODO: use NODE_DOT2 as memo(v, v, -) */
        memo = MEMO_NEW(result, args, 0);
        rb_block_call(obj, id_each, 0, 0, allary ? zip_ary : zip_i, (VALUE)memo);

        return result;
    }