Module: Enumerable
- Included in:
- Array, Dir, Enumerator, Enumerator::Generator, Hash, IO, ObjectSpace::WeakMap, Range, Struct
- Defined in:
- enum.c
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
ifself == 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 givenobject
or a given block. -
#slice_before: Returns a new Enumerator whose entries are a partition of
self
, based either on a givenobject
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
-
#all?(*args) ⇒ Object
Returns whether every element meets a given criterion.
-
#any?(*args) ⇒ Object
Returns whether any element meets a given criterion.
-
#chain(*enums) ⇒ Object
Returns an enumerator object generated from this enumerator and given enumerables.
-
#chunk {|array| ... } ⇒ Object
Each element in the returned enumerator is a 2-element array consisting of:.
-
#chunk_while {|elt_before, elt_after| ... } ⇒ Object
Creates an enumerator for each chunked elements.
-
#collect ⇒ Object
Returns an array of objects returned by the block.
-
#collect_concat ⇒ Object
Returns an array of flattened objects returned by the block.
-
#compact ⇒ Array
Returns an array of all non-
nil
elements:. -
#count(*args) ⇒ Object
Returns the count of elements, based on an argument or block criterion, if given.
-
#cycle(*args) ⇒ 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 son
times; returnsnil
:. -
#detect(*args) ⇒ Object
Returns the first element for which the block returns a truthy value.
-
#drop(n) ⇒ Array
For positive integer
n
, returns an array containing all but the firstn
elements:. -
#drop_while ⇒ Object
Calls the block with successive elements as long as the block returns a truthy value; returns an array of all elements after that point:.
-
#each_cons(n) ⇒ Object
Calls the block with each successive overlapped
n
-tuple of elements; returnsself
:. -
#each_entry(*args) ⇒ Object
Calls the given block with each element, converting multiple values from yield to an array; returns
self
:. -
#each_slice(n) ⇒ Object
Calls the block with each successive disjoint
n
-tuple of elements; returnsself
:. -
#each_with_index(*args) ⇒ Object
With a block given, calls the block with each element and its index; returns
self
:. -
#each_with_object(memo) ⇒ Object
Calls the block once for each element, passing both the element and the given object:.
-
#to_a(*args) ⇒ Array
Returns an array containing the items in
self
:. -
#filter ⇒ Object
Returns an array containing elements selected by the block.
-
#filter_map ⇒ Object
Returns an array containing truthy elements returned by the block.
-
#find(*args) ⇒ Object
Returns the first element for which the block returns a truthy value.
-
#find_all ⇒ Object
Returns an array containing elements selected by the block.
-
#find_index(*args) ⇒ Object
Returns the index of the first element that meets a specified criterion, or
nil
if no such element is found. -
#first(*args) ⇒ Object
Returns the first element or elements.
-
#flat_map ⇒ Object
Returns an array of flattened objects returned by the block.
-
#grep(pat) ⇒ Object
Returns an array of objects based elements of
self
that match the given pattern. -
#grep_v(pat) ⇒ Object
Returns an array of objects based on elements of
self
that don’t match the given pattern. -
#group_by ⇒ Object
With a block given returns a hash:.
-
#include?(object) ⇒ Boolean
Returns whether for any element
object == element
:. -
#inject(*args) ⇒ Object
Returns an object formed from operands via either:.
-
#lazy ⇒ Object
Returns an Enumerator::Lazy, which redefines most Enumerable methods to postpone enumeration and enumerate values only on an as-needed basis.
-
#map ⇒ Object
Returns an array of objects returned by the block.
-
#max(*args) ⇒ Object
Returns the element with the maximum element according to a given criterion.
-
#max_by(*args) ⇒ Object
Returns the elements for which the block returns the maximum values.
-
#include?(object) ⇒ Boolean
Returns whether for any element
object == element
:. -
#min(*args) ⇒ Object
Returns the element with the minimum element according to a given criterion.
-
#min_by(*args) ⇒ Object
Returns the elements for which the block returns the minimum values.
-
#minmax ⇒ Object
Returns a 2-element array containing the minimum and maximum elements according to a given criterion.
-
#minmax_by ⇒ Object
Returns a 2-element array containing the elements for which the block returns minimum and maximum values:.
-
#none?(*args) ⇒ Object
Returns whether no element meets a given criterion.
-
#one?(*args) ⇒ Object
Returns whether exactly one element meets a given criterion.
-
#partition ⇒ Object
With a block given, returns an array of two arrays:.
-
#reduce(*args) ⇒ Object
Returns an object formed from operands via either:.
-
#reject ⇒ Object
Returns an array of objects rejected by the block.
-
#reverse_each(*args) ⇒ Object
With a block given, calls the block with each element, but in reverse order; returns
self
:. -
#select ⇒ Object
Returns an array containing elements selected by the block.
-
#slice_after(*args) ⇒ Object
Creates an enumerator for each chunked elements.
-
#slice_before(*args) ⇒ Object
With argument
pattern
, returns an enumerator that uses the pattern to partition elements into arrays (“slices”). -
#slice_when {|elt_before, elt_after| ... } ⇒ Object
Creates an enumerator for each chunked elements.
-
#sort ⇒ Object
Returns an array containing the sorted elements of
self
. -
#sort_by ⇒ Object
With a block given, returns an array of elements of
self
, sorted according to the value returned by the block for each element. -
#sum(*args) ⇒ Object
With no block given, returns the sum of
initial_value
and the elements:. -
#take(n) ⇒ Array
For non-negative integer
n
, returns the firstn
elements:. -
#take_while ⇒ Object
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:.
-
#tally(*args) ⇒ Object
Returns a hash containing the counts of equal elements:.
-
#to_a(*args) ⇒ Array
Returns an array containing the items in
self
:. -
#to_h(*args) ⇒ Object
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:. -
#uniq ⇒ Object
With no block, returns a new array containing only unique elements; the array has no two elements
e0
ande1
such thate0.eql?(e1)
:. -
#zip(*args) ⇒ Object
With no block given, returns a new array
new_array
of size self.size whose elements are arrays.
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?.
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?.
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
}
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
.
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 #map ⇒ Object
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.
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_map ⇒ Object
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.
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;
}
|
#compact ⇒ Array
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]
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;
}
|
#count ⇒ Integer #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
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.
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.
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]]
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_while ⇒ Object
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.
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.
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.
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.
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.
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.
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]
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 #select ⇒ Object
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.
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_map ⇒ Object
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.
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.
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 #select ⇒ Object
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.
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_index ⇒ Object
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.
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;
}
|
#first ⇒ nil #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) # => []
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_map ⇒ Object
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.
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.
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.
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_by ⇒ Object
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.
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
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"
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;
}
|
#lazy ⇒ Object
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 #map ⇒ Object
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.
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;
}
|
#max ⇒ Object #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.
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_by ⇒ Object #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.
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
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;
}
|
#min ⇒ Object #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.
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_by ⇒ Object #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.
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;
}
|
#minmax ⇒ Array #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.
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_by ⇒ Object
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.
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?.
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?.
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 #partition ⇒ Object
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.
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"
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 #reject ⇒ Object
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.
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.
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 #select ⇒ Object
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.
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"]
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
}
}
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
.
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;
}
|
#sort ⇒ Array #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.
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_by ⇒ Object
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!
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"
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]]
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_while ⇒ Object
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.
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;
}
|
#tally ⇒ Object #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}
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]
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.
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);
}
|
#uniq ⇒ Array #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"]
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 theother_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]
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;
}
|