Module: Enumerable

Overview

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:

  • #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.

Instance Method Summary collapse

Instance Method Details

#all?Boolean #all?(pattern) ⇒ Boolean #all? {|element| ... } ⇒ Boolean

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?.

Overloads:

  • #all?Boolean

    Returns:

    • (Boolean)
  • #all?(pattern) ⇒ Boolean

    Returns:

    • (Boolean)
  • #all? {|element| ... } ⇒ Boolean

    Yields:

    • (element)

    Returns:

    • (Boolean)


1798
1799
1800
1801
1802
1803
1804
1805
# File 'enum.c', line 1798

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?Boolean #any?(pattern) ⇒ Boolean #any? {|element| ... } ⇒ Boolean

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?.

Overloads:

  • #any?Boolean

    Returns:

    • (Boolean)
  • #any?(pattern) ⇒ Boolean

    Returns:

    • (Boolean)
  • #any? {|element| ... } ⇒ Boolean

    Yields:

    • (element)

    Returns:

    • (Boolean)


1860
1861
1862
1863
1864
1865
1866
1867
# File 'enum.c', line 1860

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) ⇒ Object

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]


3369
3370
3371
3372
3373
3374
3375
# File 'enumerator.c', line 3369

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| ... } ⇒ Object

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
}

Yields:

  • (array)


3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
# File 'enum.c', line 3939

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| ... } ⇒ Object

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.

Yields:

  • (elt_before, elt_after)


4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
# File 'enum.c', line 4513

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;
}

#map {|element| ... } ⇒ Array #mapObject

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.

Overloads:

  • #map {|element| ... } ⇒ Array

    Yields:

    • (element)

    Returns:



637
638
639
640
641
642
643
644
645
646
647
648
649
650
# File 'enum.c', line 637

static VALUE
enum_collect(VALUE obj)
{
    VALUE ary;
    int min_argc, max_argc;

    RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);

    ary = rb_ary_new();
    min_argc = rb_block_min_max_arity(&max_argc);
    rb_lambda_call(obj, id_each, 0, 0, collect_i, min_argc, max_argc, ary);

    return ary;
}

#flat_map {|element| ... } ⇒ Array #flat_mapObject

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.

Overloads:

  • #flat_map {|element| ... } ⇒ Array

    Yields:

    • (element)

    Returns:



688
689
690
691
692
693
694
695
696
697
698
699
# File 'enum.c', line 688

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;
}

#compactArray

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]

Returns:



4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
# File 'enum.c', line 4873

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;
}

#countInteger #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

Overloads:



297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
# File 'enum.c', line 297

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 #cycle(n = nil) ⇒ Object

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.

Overloads:

  • #cycle(n = nil) {|element| ... } ⇒ nil

    Yields:

    • (element)

    Returns:

    • (nil)


3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
# File 'enum.c', line 3725

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;
}

#find(if_none_proc = nil) {|element| ... } ⇒ Object? #find(if_none_proc = nil) ⇒ Object

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.

Overloads:

  • #find(if_none_proc = nil) {|element| ... } ⇒ Object?

    Yields:

    • (element)

    Returns:



360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
# File 'enum.c', line 360

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;
}

#drop(n) ⇒ Array

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]]

Returns:



3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
# File 'enum.c', line 3602

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 #drop_whileObject

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.

Overloads:

  • #drop_while {|element| ... } ⇒ Array

    Yields:

    • (element)

    Returns:



3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
# File 'enum.c', line 3654

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 #each_cons(n) ⇒ Object

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.

Overloads:

  • #each_cons(n) { ... } ⇒ self

    Yields:

    Returns:

    • (self)


3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
# File 'enum.c', line 3243

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 #each_entry(*args) ⇒ Object

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.

Overloads:

  • #each_entry(*args) {|element| ... } ⇒ self

    Yields:

    • (element)

    Returns:

    • (self)


3075
3076
3077
3078
3079
3080
3081
# File 'enum.c', line 3075

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 #each_slice(n) ⇒ Object

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.

Overloads:

  • #each_slice(n) { ... } ⇒ self

    Yields:

    Returns:

    • (self)


3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
# File 'enum.c', line 3165

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 #each_with_index(*args) ⇒ Object

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.

Overloads:

  • #each_with_index(*args) {|element, i| ... } ⇒ self

    Yields:

    • (element, i)

    Returns:

    • (self)


2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
# File 'enum.c', line 2966

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 #each_with_object(object) ⇒ Object

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.

Overloads:

  • #each_with_object(object) {|(*args), memo_object| ... } ⇒ Object

    Yields:

    • ((*args), memo_object)

    Returns:



3284
3285
3286
3287
3288
3289
3290
3291
3292
# File 'enum.c', line 3284

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;
}

#to_a(*args) ⇒ Array

Returns an array containing the items in self:

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

Returns:



710
711
712
713
714
715
716
717
718
# File 'enum.c', line 710

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;
}

#select {|element| ... } ⇒ Array #selectObject

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.

Overloads:

  • #select {|element| ... } ⇒ Array

    Yields:

    • (element)

    Returns:



508
509
510
511
512
513
514
515
516
517
518
519
# File 'enum.c', line 508

static VALUE
enum_find_all(VALUE obj)
{
    VALUE ary;

    RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);

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

    return ary;
}

#filter_map {|element| ... } ⇒ Array #filter_mapObject

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.

Overloads:

  • #filter_map {|element| ... } ⇒ Array

    Yields:

    • (element)

    Returns:



549
550
551
552
553
554
555
556
557
558
559
560
# File 'enum.c', line 549

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? #find(if_none_proc = nil) ⇒ Object

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.

Overloads:

  • #find(if_none_proc = nil) {|element| ... } ⇒ Object?

    Yields:

    • (element)

    Returns:



360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
# File 'enum.c', line 360

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;
}

#select {|element| ... } ⇒ Array #selectObject

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.

Overloads:

  • #select {|element| ... } ⇒ Array

    Yields:

    • (element)

    Returns:



508
509
510
511
512
513
514
515
516
517
518
519
# File 'enum.c', line 508

static VALUE
enum_find_all(VALUE obj)
{
    VALUE ary;

    RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);

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

    return ary;
}

#find_index(object) ⇒ Integer? #find_index {|element| ... } ⇒ Integer? #find_indexObject

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.

Overloads:

  • #find_index(object) ⇒ Integer?

    Returns:

  • #find_index {|element| ... } ⇒ Integer?

    Yields:

    • (element)

    Returns:



431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
# File 'enum.c', line 431

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;
}

#firstnil #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)                       # => []

Overloads:

  • #firstnil

    Returns:

    • (nil)
  • #first(n) ⇒ Array

    Returns:



1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
# File 'enum.c', line 1283

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 #flat_mapObject

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.

Overloads:

  • #flat_map {|element| ... } ⇒ Array

    Yields:

    • (element)

    Returns:



688
689
690
691
692
693
694
695
696
697
698
699
# File 'enum.c', line 688

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;
}

#grep(pattern) ⇒ Array #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.

Overloads:

  • #grep(pattern) ⇒ Array

    Returns:

  • #grep(pattern) {|element| ... } ⇒ Array

    Yields:

    • (element)

    Returns:



172
173
174
175
176
# File 'enum.c', line 172

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

#grep_v(pattern) ⇒ Array #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.

Overloads:

  • #grep_v(pattern) ⇒ Array

    Returns:

  • #grep_v(pattern) {|element| ... } ⇒ Array

    Yields:

    • (element)

    Returns:



204
205
206
207
208
# File 'enum.c', line 204

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

#group_by {|element| ... } ⇒ Hash #group_byObject

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.

Overloads:

  • #group_by {|element| ... } ⇒ Hash

    Yields:

    • (element)

    Returns:



1156
1157
1158
1159
1160
1161
1162
# File 'enum.c', line 1156

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) ⇒ Boolean

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

Returns:

  • (Boolean)


2920
2921
2922
2923
2924
2925
2926
2927
# File 'enum.c', line 2920

static VALUE
enum_member(VALUE obj, VALUE val)
{
    struct MEMO *memo = MEMO_NEW(val, Qfalse, 0);

    rb_block_call(obj, id_each, 0, 0, member_i, (VALUE)memo);
    return memo->v2;
}

#inject(symbol) ⇒ Object #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"

Overloads:

  • #inject(symbol) ⇒ Object

    Returns:

  • #inject(initial_operand, symbol) ⇒ Object

    Returns:

  • #inject {|memo, operand| ... } ⇒ Object

    Yields:

    • (memo, operand)

    Returns:

  • #inject(initial_operand) {|memo, operand| ... } ⇒ Object

    Yields:

    • (memo, operand)

    Returns:



1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
# File 'enum.c', line 1004

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;
}

#lazyObject

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


1935
1936
1937
1938
1939
1940
1941
1942
# File 'enumerator.c', line 1935

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 #mapObject

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.

Overloads:

  • #map {|element| ... } ⇒ Array

    Yields:

    • (element)

    Returns:



637
638
639
640
641
642
643
644
645
646
647
648
649
650
# File 'enum.c', line 637

static VALUE
enum_collect(VALUE obj)
{
    VALUE ary;
    int min_argc, max_argc;

    RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);

    ary = rb_ary_new();
    min_argc = rb_block_min_max_arity(&max_argc);
    rb_lambda_call(obj, id_each, 0, 0, collect_i, min_argc, max_argc, ary);

    return ary;
}

#maxObject #max(n) ⇒ Array #max {|a, b| ... } ⇒ Object #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.

Overloads:

  • #max(n) ⇒ Array

    Returns:

  • #max {|a, b| ... } ⇒ Object

    Yields:

    • (a, b)
  • #max(n) {|a, b| ... } ⇒ Array

    Yields:

    • (a, b)

    Returns:



2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
# File 'enum.c', line 2441

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| ... } ⇒ Object #max_by(n) {|element| ... } ⇒ Array #max_byObject #max_by(n) ⇒ Object

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.

Overloads:

  • #max_by {|element| ... } ⇒ Object

    Yields:

    • (element)
  • #max_by(n) {|element| ... } ⇒ Array

    Yields:

    • (element)

    Returns:



2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
# File 'enum.c', line 2759

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;
}

#include?(object) ⇒ Boolean

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

Returns:

  • (Boolean)


2920
2921
2922
2923
2924
2925
2926
2927
# File 'enum.c', line 2920

static VALUE
enum_member(VALUE obj, VALUE val)
{
    struct MEMO *memo = MEMO_NEW(val, Qfalse, 0);

    rb_block_call(obj, id_each, 0, 0, member_i, (VALUE)memo);
    return memo->v2;
}

#minObject #min(n) ⇒ Array #min {|a, b| ... } ⇒ Object #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.

Overloads:

  • #min(n) ⇒ Array

    Returns:

  • #min {|a, b| ... } ⇒ Object

    Yields:

    • (a, b)
  • #min(n) {|a, b| ... } ⇒ Array

    Yields:

    • (a, b)

    Returns:



2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
# File 'enum.c', line 2319

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| ... } ⇒ Object #min_by(n) {|element| ... } ⇒ Array #min_byObject #min_by(n) ⇒ Object

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.

Overloads:

  • #min_by {|element| ... } ⇒ Object

    Yields:

    • (element)
  • #min_by(n) {|element| ... } ⇒ Array

    Yields:

    • (element)

    Returns:



2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
# File 'enum.c', line 2685

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;
}

#minmaxArray #minmax {|a, b| ... } ⇒ Array

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.

Overloads:

  • #minmaxArray

    Returns:

  • #minmax {|a, b| ... } ⇒ Array

    Yields:

    • (a, b)

    Returns:



2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
# File 'enum.c', line 2605

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| ... } ⇒ Array #minmax_byObject

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.

Overloads:

  • #minmax_by {|element| ... } ⇒ Array

    Yields:

    • (element)

    Returns:



2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
# File 'enum.c', line 2870

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?Boolean #none?(pattern) ⇒ Boolean #none? {|element| ... } ⇒ Boolean

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?.

Overloads:

  • #none?Boolean

    Returns:

    • (Boolean)
  • #none?(pattern) ⇒ Boolean

    Returns:

    • (Boolean)
  • #none? {|element| ... } ⇒ Boolean

    Yields:

    • (element)

    Returns:

    • (Boolean)


2209
2210
2211
2212
2213
2214
2215
2216
2217
# File 'enum.c', line 2209

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?Boolean #one?(pattern) ⇒ Boolean #one? {|element| ... } ⇒ Boolean

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?.

Overloads:

  • #one?Boolean

    Returns:

    • (Boolean)
  • #one?(pattern) ⇒ Boolean

    Returns:

    • (Boolean)
  • #one? {|element| ... } ⇒ Boolean

    Yields:

    • (element)

    Returns:

    • (Boolean)


2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
# File 'enum.c', line 2147

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| ... } ⇒ Array #partitionObject

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.

Overloads:

  • #partition {|element| ... } ⇒ Array

    Yields:

    • (element)

    Returns:



1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
# File 'enum.c', line 1101

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);
}

#inject(symbol) ⇒ Object #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"

Overloads:

  • #inject(symbol) ⇒ Object

    Returns:

  • #inject(initial_operand, symbol) ⇒ Object

    Returns:

  • #inject {|memo, operand| ... } ⇒ Object

    Yields:

    • (memo, operand)

    Returns:

  • #inject(initial_operand) {|memo, operand| ... } ⇒ Object

    Yields:

    • (memo, operand)

    Returns:



1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
# File 'enum.c', line 1004

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;
}

#reject {|element| ... } ⇒ Array #rejectObject

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.

Overloads:

  • #reject {|element| ... } ⇒ Array

    Yields:

    • (element)

    Returns:



592
593
594
595
596
597
598
599
600
601
602
603
# File 'enum.c', line 592

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 #reverse_each(*args) ⇒ Object

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.

Overloads:

  • #reverse_each(*args) {|element| ... } ⇒ self

    Yields:

    • (element)

    Returns:

    • (self)


3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
# File 'enum.c', line 3005

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 #selectObject

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.

Overloads:

  • #select {|element| ... } ⇒ Array

    Yields:

    • (element)

    Returns:



508
509
510
511
512
513
514
515
516
517
518
519
# File 'enum.c', line 508

static VALUE
enum_find_all(VALUE obj)
{
    VALUE ary;

    RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);

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

    return ary;
}

#slice_after(pattern) ⇒ Object #slice_after {|elt| ... } ⇒ Object

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"]

Overloads:

  • #slice_after {|elt| ... } ⇒ Object

    Yields:

    • (elt)


4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
# File 'enum.c', line 4290

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) ⇒ Object #slice_before {|elt| ... } ⇒ Object

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
  }
}

Overloads:

  • #slice_before {|elt| ... } ⇒ Object

    Yields:

    • (elt)


4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
# File 'enum.c', line 4168

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| ... } ⇒ Object

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.

Yields:

  • (elt_before, elt_after)


4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
# File 'enum.c', line 4447

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;
}

#sortArray #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.

Overloads:



1330
1331
1332
1333
1334
# File 'enum.c', line 1330

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

#sort_by {|element| ... } ⇒ Array #sort_byObject

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!

Overloads:

  • #sort_by {|element| ... } ⇒ Array

    Yields:

    • (element)

    Returns:



1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
# File 'enum.c', line 1650

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) ⇒ Numeric #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"

Overloads:

  • #sum(initial_value = 0) ⇒ Numeric

    Returns:

  • #sum(initial_value = 0) {|element| ... } ⇒ Object

    Yields:

    • (element)

    Returns:



4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
# File 'enum.c', line 4752

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

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]]

Returns:



3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
# File 'enum.c', line 3513

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 #take_whileObject

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.

Overloads:

  • #take_while {|element| ... } ⇒ Array

    Yields:

    • (element)

    Returns:



3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
# File 'enum.c', line 3559

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;
}

#tallyObject #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}

Overloads:



1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
# File 'enum.c', line 1228

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

Returns an array containing the items in self:

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

Returns:



710
711
712
713
714
715
716
717
718
# File 'enum.c', line 710

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;
}

#to_h(*args) ⇒ Hash #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.

Overloads:

  • #to_h(*args) ⇒ Hash

    Returns:

  • #to_h(*args) {|element| ... } ⇒ Hash

    Yields:

    • (element)

    Returns:



767
768
769
770
771
772
# File 'enum.c', line 767

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);
}

#uniqArray #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"]

Overloads:

  • #uniqArray

    Returns:

  • #uniq {|element| ... } ⇒ Array

    Yields:

    • (element)

    Returns:



4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
# File 'enum.c', line 4837

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 #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]

Overloads:

  • #zip(*other_enums) ⇒ Array

    Returns:

  • #zip(*other_enums) {|array| ... } ⇒ nil

    Yields:

    • (array)

    Returns:

    • (nil)


3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
# File 'enum.c', line 3448

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;
}