module Indexable(T)

Overview

A container that allows accessing elements via a numeric index.

Indexing starts at0. A negative index is assumed to be relative to the end of the container:-1 indicates the last element, -2 is the next to last element, and so on.

Types including this module are typicallyArray-like types.

Stability guarantees

Several methods inIndexable, such as#bsearch and#cartesian_product, require the collection to bestable; that is, calling#each(&) over and over again should always yield the same elements, provided the collection is not mutated between the calls. In particular,#each(&) itself should not mutate the collection throughout the loop. Stability of anIndexable is guaranteed if the following criteria are met:

The standard library assumes that all including types ofIndexable are always stable. It is undefined behavior to implement anIndexable that is not stable or only conditionally stable.

Included Modules

Direct including types

Defined in:

indexable.cr

Class Method Summary

Instance Method Summary

Instance methods inherited from module Enumerable(T)

accumulate(initial : U) : Array(U) forall U
accumulate : Array(T)
accumulate(initial : U, &block : U, T -> U) : Array(U) forall U
accumulate(&block : T, T -> T) : Array(T)
accumulate
, all?(& : T -> ) : Bool
all?(pattern) : Bool
all? : Bool
all?
, any?(& : T -> ) : Bool
any?(pattern) : Bool
any? : Bool
any?
, chunks(&block : T -> U) forall U chunks, compact_map(& : T -> _) compact_map, count(& : T -> ) : Int32
count(item) : Int32
count
, cycle(n, & : T -> ) : Nil
cycle(& : T -> ) : Nil
cycle
, each(& : T -> ) each, each_cons(count : Int, reuse = false, &) each_cons, each_cons_pair(& : T, T -> ) : Nil each_cons_pair, each_slice(count : Int, reuse = false, &) each_slice, each_step(n : Int, *, offset : Int = 0, & : T -> ) : Nil each_step, each_with_index(offset = 0, &) each_with_index, each_with_object(obj : U, & : T, U -> ) : U forall U each_with_object, empty? : Bool empty?, find(if_none = nil, & : T -> ) find, find!(& : T -> ) : T find!, find_value(if_none = nil, & : T -> ) find_value, first(&)
first(count : Int) : Array(T)
first : T
first
, first? : T | Nil first?, flat_map(& : T -> _) flat_map, group_by(& : T -> U) forall U group_by, in_groups_of(size : Int, filled_up_with : U = nil) forall U
in_groups_of(size : Int, filled_up_with : U = nil, reuse = false, &) forall U
in_groups_of
, in_slices_of(size : Int) : Array(Array(T)) in_slices_of, includes?(obj) : Bool includes?, index(& : T -> ) : Int32 | Nil
index(obj) : Int32 | Nil
index
, index!(& : T -> ) : Int32
index!(obj) : Int32
index!
, index_by(& : T -> U) : Hash(U, T) forall U index_by, join(io : IO, separator = "") : Nil
join(separator, io : IO) : Nil
join(separator = "") : String
join(io : IO, separator = "", & : T, IO -> )
join(separator, io : IO, &)
join(separator = "", & : T -> )
join
, map(& : T -> U) : Array(U) forall U map, map_with_index(offset = 0, & : T, Int32 -> U) : Array(U) forall U map_with_index, max(count : Int) : Array(T)
max : T
max
, max? : T | Nil max?, max_by(& : T -> U) : T forall U max_by, max_by?(& : T -> U) : T | Nil forall U max_by?, max_of(& : T -> U) : U forall U max_of, max_of?(& : T -> U) : U | Nil forall U max_of?, min(count : Int) : Array(T)
min : T
min
, min? : T | Nil min?, min_by(& : T -> U) : T forall U min_by, min_by?(& : T -> U) : T | Nil forall U min_by?, min_of(& : T -> U) : U forall U min_of, min_of?(& : T -> U) : U | Nil forall U min_of?, minmax : Tuple(T, T) minmax, minmax? : Tuple(T | Nil, T | Nil) minmax?, minmax_by(& : T -> U) : Tuple(T, T) forall U minmax_by, minmax_by?(& : T -> U) : Tuple(T, T) | Tuple(Nil, Nil) forall U minmax_by?, minmax_of(& : T -> U) : Tuple(U, U) forall U minmax_of, minmax_of?(& : T -> U) : Tuple(U, U) | Tuple(Nil, Nil) forall U minmax_of?, none?(& : T -> ) : Bool
none?(pattern) : Bool
none? : Bool
none?
, one?(& : T -> ) : Bool
one?(pattern) : Bool
one? : Bool
one?
, partition(& : T -> ) : Tuple(Array(T), Array(T))
partition(type : U.class) forall U
partition
, present? : Bool present?, product(initial : Number)
product
product(initial : Number, & : T -> )
product(& : T -> _)
product
, reduce(memo, &)
reduce(&)
reduce
, reduce?(&) reduce?, reject(& : T -> )
reject(type : U.class) forall U
reject(pattern) : Array(T)
reject
, sample(n : Int, random : Random | Nil = nil) : Array(T)
sample(random : Random | Nil = nil) : T
sample
, select(& : T -> )
select(type : U.class) : Array(U) forall U
select(pattern) : Array(T)
select
, size : Int32 size, skip(count : Int) skip, skip_while(& : T -> ) : Array(T) skip_while, sum(initial)
sum
sum(initial, & : T -> )
sum(& : T -> )
sum
, take_while(& : T -> ) : Array(T) take_while, tally(hash)
tally : Hash(T, Int32)
tally
, tally_by(hash, &)
tally_by(&block : T -> U) : Hash(U, Int32) forall U
tally_by
, to_a : Array(T)
to_a(& : T -> U) : Array(U) forall U
to_a
, to_h
to_h(& : T -> Tuple(K, V)) forall K, V
to_h
, to_set : Set(T)
to_set(&block : T -> U) : Set(U) forall U
to_set
, zip(*others : Indexable | Iterable | Iterator, &)
zip(*others : Indexable | Iterable | Iterator)
zip
, zip?(*others : Indexable | Iterable | Iterator, &)
zip?(*others : Indexable | Iterable | Iterator)
zip?

Class methods inherited from module Enumerable(T)

element_type(x) element_type

Instance methods inherited from module Iterable(T)

chunk(reuse = false, &block : T -> U) forall U chunk, chunk_while(reuse : Bool | Array(T) = false, &block : T, T -> B) forall B chunk_while, cycle(n)
cycle
cycle
, each each, each_cons(count : Int, reuse = false) each_cons, each_cons_pair each_cons_pair, each_slice(count : Int, reuse = false) each_slice, each_step(n : Int)
each_step(n : Int, *, offset : Int)
each_step
, each_with_index(offset = 0) each_with_index, each_with_object(obj) each_with_object, slice_after(reuse : Bool | Array(T) = false, &block : T -> B) forall B
slice_after(pattern, reuse : Bool | Array(T) = false)
slice_after
, slice_before(reuse : Bool | Array(T) = false, &block : T -> B) forall B
slice_before(pattern, reuse : Bool | Array(T) = false)
slice_before
, slice_when(reuse : Bool | Array(T) = false, &block : T, T -> B) forall B slice_when

Class Method Detail

def self.cartesian_product(indexables : Indexable(Indexable)) #

Returns anArray of all ordered combinations of elements taken from each of theindexables asArrays. Traversal of elements starts from the lastIndexable. Ifindexables is empty, the returned product contains exactly one emptyArray.

#cartesian_product is preferred over this class method when the quantity ofindexables is known in advance.

Indexable.cartesian_product([[1, 2, 3], [4, 5]]) # => [[1, 4], [1, 5], [2, 4], [2, 5], [3, 4], [3, 5]]

def self.each_cartesian(indexables : Indexable(Indexable), reuse = false, &) #

Yields each ordered combination of the elements taken from each of the indexables asArrays. Traversal of elements starts from the lastIndexable. Ifindexables is empty, yields an emptyArray exactly once.

#each_cartesian is preferred over this class method when the quantity of indexables is known in advance.

Indexable.each_cartesian([%w[Alice Bob Carol], [1, 2]]) do |name, n|
  puts "#{n}. #{name}"
end

Prints

1. Alice
2. Alice
1. Bob
2. Bob
1. Carol
2. Carol

By default, a newArray is created and yielded for each combination.

  • Ifreuse is anArray, it will be reused
  • Ifreuse is truthy, the method will create a newArray and reuse it
  • Ifreuse is falsey, noArrays will be reused.

This can be used to prevent many memory allocations when each combination of interest is to be used in a read-only fashion.


def self.each_cartesian(indexables : Indexable(Indexable), reuse = false) #

Returns an iterator that enumerates the ordered combinations of elements taken from theindexables asArrays. Traversal of elements starts from the lastIndexable. Ifindexables is empty, the returned iterator produces one emptyArray, then stops.

#each_cartesian is preferred over this class method when the quantity of indexables is known in advance.

iter = Indexable.each_cartesian([%w[N S], %w[E W]])
iter.next # => ["N", "E"]
iter.next # => ["N", "W"]
iter.next # => ["S", "E"]
iter.next # => ["S", "W"]
iter.next # => Iterator::Stop::INSTANCE

By default, a newArray is created and returned for each combination.

  • Ifreuse is anArray, it will be reused
  • Ifreuse is truthy, the method will create a newArray and reuse it
  • Ifreuse is falsey, noArrays will be reused.

This can be used to prevent many memory allocations when each combination of interest is to be used in a read-only fashion.


Instance Method Detail

def [](index : Int) #

Returns the element at the givenindex.

Negative indices can be used to start counting from the end of the array. RaisesIndexError if trying to access an element outside the array's range.

ary = ['a', 'b', 'c']
ary[0]  # => 'a'
ary[2]  # => 'c'
ary[-1] # => 'c'
ary[-2] # => 'b'

ary[3]  # raises IndexError
ary[-4] # raises IndexError

def []?(index : Int) #

Returns the element at the givenindex.

Negative indices can be used to start counting from the end of the array. Returnsnil if trying to access an element outside the array's range.

ary = ['a', 'b', 'c']
ary[0]?  # => 'a'
ary[2]?  # => 'c'
ary[-1]? # => 'c'
ary[-2]? # => 'b'

ary[3]?  # => nil
ary[-4]? # => nil

def bsearch(& : T -> _) #

By using binary search, returns the first element for which the passed block returns a truthy value.

If the block returns a falsey value, the element to be found lies behind. If the block returns a truthy value, the element to be found is itself or lies in front.

Binary search needs the collection to be sorted in regards to the search criterion.

Returnsnil if the block didn't return a truthy value for any element.

[2, 5, 7, 10].bsearch { |x| x >= 4 } # => 5
[2, 5, 7, 10].bsearch { |x| x > 10 } # => nil

def bsearch_index(& : T, Int32 -> _) #

By using binary search, returns the index of the first element for which the passed block returns a truthy value.

If the block returns a falsey value, the element to be found lies behind. If the block returns a truthy value, the element to be found is itself or lies in front.

Binary search needs the collection to be sorted in regards to the search criterion.

Returnsnil if the block didn't return a truthy value for any element.

[2, 5, 7, 10].bsearch_index { |x, i| x >= 4 } # => 1
[2, 5, 7, 10].bsearch_index { |x, i| x > 10 } # => nil

def cartesian_product(*others : Indexable) #

Returns anArray of all ordered combinations of elements taken from each ofself andothers asTuples. Traversal of elements starts from the lastIndexable argument.

[1, 2, 3].cartesian_product({'a', 'b'})                     # => [{1, 'a'}, {1, 'b'}, {2, 'a'}, {2, 'b'}, {3, 'a'}, {3, 'b'}]
['a', 'b'].cartesian_product({1, 2}, {'c', 'd'}).map &.join # => ["a1c", "a1d", "a2c", "a2d", "b1c", "b1d", "b2c", "b2d"]

def combinations(size : Int = self.size) #

Returns anArray with all possible combinations ofsize ofself.

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

def dig(index : Int, *subindexes) #

Traverses the depth of a structure and returns the value, otherwise raisesIndexError.

ary = [{1, 2, 3, {4, 5, 6}}]
ary.dig(0, 3, 2) # => 6
ary.dig(0, 3, 3) # raises IndexError

def dig?(index : Int, *subindexes) #

Traverses the depth of a structure and returns the value. Returnsnil if not found.

ary = [{1, 2, 3, {4, 5, 6}}]
ary.dig?(0, 3, 2) # => 6
ary.dig?(0, 3, 3) # => nil

def each(& : T -> ) #

Calls the given block once for each element inself, passing that element as a parameter.

a = ["a", "b", "c"]
a.each { |x| print x, " -- " }

produces:

a -- b -- c --

def each #

Returns anIterator for the elements ofself.

a = ["a", "b", "c"]
iter = a.each
iter.next # => "a"
iter.next # => "b"

The returned iterator keeps a reference toself: if the array changes, the returned values of the iterator change as well.


def each(*, start : Int, count : Int, & : T -> ) #

Calls the given block once forcount number of elements inself starting from indexstart, passing each element as a parameter.

Negative indices count backward from the end of the array. (-1 is the last element).

RaisesIndexError if the starting index is out of range. RaisesArgumentError ifcount is a negative number.

array = ["a", "b", "c", "d", "e"]
array.each(start: 1, count: 3) { |x| print x, " -- " }

produces:

b -- c -- d --

def each(*, within range : Range, & : T -> ) #

Calls the given block once for all elements at indices within the given range, passing each element as a parameter.

RaisesIndexError if the starting index is out of range.

array = ["a", "b", "c", "d", "e"]
array.each(within: 1..3) { |x| print x, " -- " }

produces:

b -- c -- d --

def each_cartesian(*others : Indexable, &) #

Yields each ordered combination of the elements taken from each ofself andothers as aTuple. Traversal of elements starts from the lastIndexable argument.

["Alice", "Bob"].each_cartesian({1, 2, 3}) do |name, n|
  puts "#{n}. #{name}"
end

Prints

1. Alice
2. Alice
3. Alice
1. Bob
2. Bob
3. Bob

def each_cartesian(*others : Indexable) #

Returns an iterator that enumerates the ordered combinations of elements taken from each ofself andothers asTuples. Traversal of elements starts from the lastIndexable argument.

iter = {1, 2, 3}.each_cartesian({'a', 'b'})
iter.next # => {1, 'a'}
iter.next # => {1, 'b'}
iter.next # => {2, 'a'}
iter.next # => {2, 'b'}
iter.next # => {3, 'a'}
iter.next # => {3, 'b'}
iter.next # => Iterator::Stop::INSTANCE

def each_combination(size : Int = self.size, reuse = false, &) : Nil #

Yields each possible combination ofsize ofself.

a = [1, 2, 3]
sums = [] of Int32
a.each_combination(2) { |p| sums << p.sum } # => nil
sums                                        # => [3, 4, 5]

By default, a new array is created and yielded for each combination. Ifreuse is given, the array can be reused: ifreuse is anArray, this array will be reused; ifreuse if truthy, the method will create a new array and reuse it. This can be used to prevent many memory allocations when each slice of interest is to be used in a read-only fashion.


def each_combination(size : Int = self.size, reuse = false) #

Returns anIterator over each possible combination ofsize ofself.

iter = [1, 2, 3, 4].each_combination(3)
iter.next # => [1, 2, 3]
iter.next # => [1, 2, 4]
iter.next # => [1, 3, 4]
iter.next # => [2, 3, 4]
iter.next # => #<Iterator::Stop>

By default, a new array is created and returned for each combination. Ifreuse is given, the array can be reused: ifreuse is anArray, this array will be reused; ifreuse if truthy, the method will create a new array and reuse it. This can be used to prevent many memory allocations when each slice of interest is to be used in a read-only fashion.


def each_index(& : Int32 -> ) : Nil #

Calls the given block once for each index inself, passing that index as a parameter.

a = ["a", "b", "c"]
a.each_index { |x| print x, " -- " }

produces:

0 -- 1 -- 2 --

def each_index #

Returns anIterator for each index inself.

a = ["a", "b", "c"]
iter = a.each_index
iter.next # => 0
iter.next # => 1

The returned iterator keeps a reference toself. If the array changes, the returned values of the iterator will change as well.


def each_index(*, start : Int, count : Int, &) #

Calls the given block once forcount number of indices inself starting from indexstart, passing each index as a parameter.

Negative indices count backward from the end of the array. (-1 is the last element).

RaisesIndexError if the starting index is out of range. RaisesArgumentError ifcount is a negative number.

array = ["a", "b", "c", "d", "e"]
array.each_index(start: -3, count: 2) { |x| print x, " -- " }

produces:

2 -- 3 --

def each_permutation(size : Int = self.size, reuse = false, &) : Nil #

Yields each possible permutation ofsize ofself.

a = [1, 2, 3]
sums = [] of Int32
a.each_permutation(2) { |p| sums << p.sum } # => nil
sums                                        # => [3, 4, 3, 5, 4, 5]

By default, a new array is created and yielded for each permutation. Ifreuse is given, the array can be reused: ifreuse is anArray, this array will be reused; ifreuse if truthy, the method will create a new array and reuse it. This can be used to prevent many memory allocations when each slice of interest is to be used in a read-only fashion.


def each_permutation(size : Int = self.size, reuse = false) #

Returns anIterator over each possible permutation ofsize ofself.

iter = [1, 2, 3].each_permutation
iter.next # => [1, 2, 3]
iter.next # => [1, 3, 2]
iter.next # => [2, 1, 3]
iter.next # => [2, 3, 1]
iter.next # => [3, 1, 2]
iter.next # => [3, 2, 1]
iter.next # => #<Iterator::Stop>

By default, a new array is created and returned for each permutation. Ifreuse is given, the array can be reused: ifreuse is anArray, this array will be reused; ifreuse if truthy, the method will create a new array and reuse it. This can be used to prevent many memory allocations when each slice of interest is to be used in a read-only fashion.


def each_repeated_combination(size : Int = self.size, reuse = false, &) : Nil #

Yields each possible combination with repeated elements ofsize of self.

a = [1, 2, 3]
sums = [] of Int32
a.each_repeated_combination(2) { |p| sums << p.sum } # => nil
sums                                                 # => [2, 3, 4, 4, 5, 6]

By default, a new array is created and yielded for each combination. Ifreuse is given, the array can be reused: ifreuse is anArray, this array will be reused; ifreuse if truthy, the method will create a new array and reuse it. This can be used to prevent many memory allocations when each slice of interest is to be used in a read-only fashion.


def each_repeated_combination(size : Int = self.size, reuse = false) #

Returns anIterator over each possible combination with repeated elements ofsize ofself.

iter = [1, 2, 3].each_repeated_combination(2)
iter.next # => [1, 1]
iter.next # => [1, 2]
iter.next # => [1, 3]
iter.next # => [2, 2]
iter.next # => [2, 3]
iter.next # => [3, 3]
iter.next # => #<Iterator::Stop>

By default, a new array is created and returned for each combination. Ifreuse is given, the array can be reused: ifreuse is anArray, this array will be reused; ifreuse if truthy, the method will create a new array and reuse it. This can be used to prevent many memory allocations when each slice of interest is to be used in a read-only fashion.


def empty? : Bool #

Returnstrue ifself is empty,false otherwise.

([] of Int32).empty? # => true
([1]).empty?         # => false

def equals?(other : Indexable, &) : Bool #

Optimized version of#equals? used whenother is also anIndexable.


def equals?(other, &) #

Determines ifself equalsother according to a comparison done by the given block.

Ifself's size is the same asother's size, this method yields elements fromself andother in tandem: if the block returns true for all of them, this method returnstrue. Otherwise it returnsfalse.

a = [1, 2, 3]
b = ["a", "ab", "abc"]
a.equals?(b) { |x, y| x == y.size } # => true
a.equals?(b) { |x, y| x == y }      # => false

def fetch(index : Int, &) #

Returns the element at the givenindex, if in bounds, otherwise executes the given block with the index and returns its value.

a = [:foo, :bar]
a.fetch(0) { :default_value }    # => :foo
a.fetch(2) { :default_value }    # => :default_value
a.fetch(2) { |index| index * 3 } # => 6

def fetch(index, default) #

Returns the value at the index given byindex, or when not found the value given bydefault.

a = [:foo, :bar]
a.fetch(0, :default_value) # => :foo
a.fetch(2, :default_value) # => :default_value

def find(if_none, _offset offset : Int, & : T -> ) #

Returns the first element in the indexable for which the passed block is truthy, starting from the givenoffset.

Accepts an optional parameterif_none, to set what gets returned if no element is found (defaults tonil).

[1, 2, 3, 4].find { |i| i > 2 }        # => 3
[1, 2, 3, 4].find(-1) { |i| i > 8 }    # => -1
[1, 2, 3, 4].find(-1, 2) { |i| i < 2 } # => -1

def find(if_none = nil, *, offset : Int, & : T -> ) #

Returns the first element in the indexable for which the passed block is truthy, starting from the givenoffset.

Accepts an optional parameterif_none, to set what gets returned if no element is found (defaults tonil).

[1, 2, 3, 4].find { |i| i > 2 }        # => 3
[1, 2, 3, 4].find(-1) { |i| i > 8 }    # => -1
[1, 2, 3, 4].find(-1, 2) { |i| i < 2 } # => -1

def find!(offset : Int = 0, & : T -> ) #

Returns the first element in the indexable for which the passed block is truthy, starting from the givenoffset. RaisesEnumerable::NotFoundError if there is no element for which the block is truthy.

[1, 2, 3, 4].find! { |i| i > 2 }     # => 3
[1, 2, 3, 4].find!(3) { |i| i > 2 }  # => 4
[1, 2, 3, 4].find! { |i| i > 8 }     # => raises Enumerable::NotFoundError
[1, 2, 3, 4].find!(-5) { |i| i > 2 } # => raises Enumerable::NotFoundError

def first(&) #

Returns the first element in the collection, If the collection is empty, calls the block and returns its value.

([1, 2, 3]).first { 4 }   # => 1
([] of Int32).first { 4 } # => 4

def hash(hasher) #

def index(object, offset : Int = 0) #

Returns the index of the first appearance ofobject inself starting from the givenoffset, ornil ifobject is not inself.

[1, 2, 3, 1, 2, 3].index(2, offset: 2) # => 4

def index(offset : Int = 0, & : T -> ) #

Returns the index of the first object inself for which the block is truthy, starting from the givenoffset, ornil if no match is found.

[1, 2, 3, 1, 2, 3].index(offset: 2) { |x| x < 2 } # => 3

def index!(obj, offset : Int = 0) #

Returns the index of the first appearance ofobj inself starting from the givenoffset. RaisesEnumerable::NotFoundError if obj is not inself.

[1, 2, 3, 1, 2, 3].index!(2, offset: 2) # => 4

def index!(offset : Int = 0, & : T -> ) #

Returns the index of the first object inself for which the block is truthy, starting from the givenoffset. Raises Enumerable::NotFoundError if no match is found.

[1, 2, 3, 1, 2, 3].index!(offset: 2) { |x| x < 2 } # => 3

def join(separator : String | Char | Number = "") : String #

Optimized version ofEnumerable#join that performs better when all of the elements in this indexable are strings: the total string bytesize to return can be computed before creating the final string, which performs better because there's no need to do reallocations.


def last : T #

Returns the last element ofself if it's not empty, or raisesIndexError.

([1, 2, 3]).last   # => 3
([] of Int32).last # raises IndexError

def last(&) #

Returns the last element ofself if it's not empty, or the given block's value.

([1, 2, 3]).last { 4 }   # => 3
([] of Int32).last { 4 } # => 4

def last? : T | Nil #

Returns the last element ofself if it's not empty, ornil.

([1, 2, 3]).last?   # => 3
([] of Int32).last? # => nil

def permutations(size : Int = self.size) : Array(Array(T)) #

Returns anArray with all possible permutations ofsize ofself.

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

def repeated_combinations(size : Int = self.size) : Array(Array(T)) #

Returns anArray with all possible combinations with repeated elements of size ofself.

a = [1, 2, 3]

pp a.repeated_combinations
pp a.repeated_combinations(2)

produces:

[[1, 1, 1],
 [1, 1, 2],
 [1, 1, 3],
 [1, 2, 2],
 [1, 2, 3],
 [1, 3, 3],
 [2, 2, 2],
 [2, 2, 3],
 [2, 3, 3],
 [3, 3, 3]]
[[1, 1], [1, 2], [1, 3], [2, 2], [2, 3], [3, 3]]

def reverse_each(& : T -> ) : Nil #

Same as#each, but works in reverse.


def reverse_each #

Returns anIterator over the elements ofself in reverse order.


def rindex(value, offset = size - 1) #

Returns the index of the last appearance ofvalue inself, or nil if the value is not inself.

Ifoffset is given, it defines the position toend the search (elements beyond this point are ignored).

[1, 2, 3, 2, 3].rindex(2)            # => 3
[1, 2, 3, 2, 3].rindex(2, offset: 2) # => 1

def rindex(offset = size - 1, & : T -> ) #

Returns the index of the first object inself for which the block is truthy, starting from the last object, ornil if no match is found.

Ifoffset is given, the search starts from that index towards the first elements inself.

[1, 2, 3, 2, 3].rindex { |x| x < 3 }            # => 3
[1, 2, 3, 2, 3].rindex(offset: 2) { |x| x < 3 } # => 1

def rindex!(value, offset = size - 1) #

Returns the index of the last appearance ofvalue inself, or nil if the value is not inself.

Ifoffset is given, it defines the position toend the search (elements beyond this point are ignored).

[1, 2, 3, 2, 3].rindex(2)            # => 3
[1, 2, 3, 2, 3].rindex(2, offset: 2) # => 1

RaisesEnumerable::NotFoundError ifvalue is not inself.


def rindex!(offset = size - 1, & : T -> ) #

Returns the index of the first object inself for which the block is truthy, starting from the last object, ornil if no match is found.

Ifoffset is given, the search starts from that index towards the first elements inself.

[1, 2, 3, 2, 3].rindex { |x| x < 3 }            # => 3
[1, 2, 3, 2, 3].rindex(offset: 2) { |x| x < 3 } # => 1

RaisesEnumerable::NotFoundError if no match is found.


def sample(n : Int, random : Random | Nil = nil) : Array(T) #

Returns anArray ofn random elements fromself. All elements have equal probability of being drawn. Sampling is done without replacement; if n is larger than the size of this collection, the returnedArray has the same size asself.

RaisesArgumentError ifn is negative.

[1, 2, 3, 4, 5].sample(2) # => [3, 5]
{1, 2, 3, 4, 5}.sample(2) # => [3, 4]

Uses therandom instance when provided if the randomness needs to be controlled or to follow some traits. For example the following calls use a custom seed or a secure random source:

{1, 2, 3, 4, 5}.sample(2, Random.new(1))  # => [1, 5]
{1, 2, 3, 4, 5}.sample(2, Random::Secure) # => [2, 5]

Ifself is not empty andn is equal to 1, calls#sample(random) exactly once. Thus,random will be left in a different state compared to the implementation inEnumerable.


def sample(random : Random | Nil = nil) #

Optimized version ofEnumerable#sample that runs in O(1) time.

a = [1, 2, 3]
a.sample # => 3
a.sample # => 1

Uses therandom instance when provided if the randomness needs to be controlled or to follow some traits. For example the following sample will always return the same value:

a = [1, 2, 3]
a.sample(Random.new(1)) # => 2
a.sample(Random.new(1)) # => 2

abstract def size #

Returns the number of elements in this container.


def to_a(& : T -> U) : Array(U) forall U #

Returns anArray with the results of runningblock against each element of the collection.

{1, 2, 3}.to_a { |i| i * 2 } # => [2, 4, 6]

abstract def unsafe_fetch(index : Int) #

Returns the element at the givenindex, without doing any bounds check.

Indexable makes sure to invoke this method withindex in0...size, so converting negative indices to positive ones is not needed here.

Clients never invoke this method directly. Instead, they access elements with#[](index) and#[]?(index).

This method should only be directly invoked if you are absolutely sure the index is in bounds, to avoid a bounds check for a small boost of performance.


def values_at(*indexes : Int) #

Returns aTuple populated with the elements at the given indexes. RaisesIndexError if any index is invalid.

["a", "b", "c", "d"].values_at(0, 2) # => {"a", "c"}