module Indexable(T)
Overview
A container that allows accessing elements via a numeric index.
Indexing starts at 0
. 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 typically Array
-like types.
Included Modules
Direct including types
Defined in:
indexable.crClass Method Summary
- .cartesian_product(indexables : Indexable(Indexable))
- .each_cartesian(indexables : Indexable(Indexable), reuse = false, &)
Yields each ordered combination of the elements taken from each of the indexables as
Array
s. - .each_cartesian(indexables : Indexable(Indexable), reuse = false)
Returns an iterator that enumerates the ordered combinations of elements taken from the indexables as
Array
s.
Instance Method Summary
- #[](index : Int)
Returns the element at the given index.
- #[]?(index : Int)
Returns the element at the given index.
- #bsearch(& : T -> _)
By using binary search, returns the first element for which the passed block returns a truthy value.
- #bsearch_index(& : T, Int32 -> _)
By using binary search, returns the index of the first element for which the passed block returns a truthy value.
- #cartesian_product(*others : Indexable)
- #combinations(size : Int = self.size)
- #dig(index : Int, *subindexes)
Traverses the depth of a structure and returns the value, otherwise raises
IndexError
. - #dig?(index : Int, *subindexes)
Traverses the depth of a structure and returns the value.
- #each(& : T -> )
Calls the given block once for each element in
self
, passing that element as a parameter. - #each
Returns an
Iterator
for the elements ofself
. - #each(*, start : Int, count : Int, & : T -> )
Calls the given block once for
count
number of elements inself
starting from indexstart
, passing each element as a parameter. - #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. - #each_cartesian(*others : Indexable, &)
Yields each ordered combination of the elements taken from each of
self
and others as aTuple
. - #each_cartesian(*others : Indexable)
Returns an iterator that enumerates the ordered combinations of elements taken from each of
self
and others asTuple
s. - #each_combination(size : Int = self.size, reuse = false, &) : Nil
- #each_combination(size : Int = self.size, reuse = false)
- #each_index(& : Int32 -> ) : Nil
Calls the given block once for each index in
self
, passing that index as a parameter. - #each_index
Returns an
Iterator
for each index inself
. - #each_index(*, start : Int, count : Int, &)
Calls the given block once for
count
number of indices inself
starting from indexstart
, passing each index as a parameter. - #each_permutation(size : Int = self.size, reuse = false, &) : Nil
Yields each possible permutation of size of
self
. - #each_permutation(size : Int = self.size, reuse = false)
Returns an
Iterator
over each possible permutation of size ofself
. - #each_repeated_combination(size : Int = self.size, reuse = false, &) : Nil
- #each_repeated_combination(size : Int = self.size, reuse = false)
- #empty? : Bool
Returns
true
ifself
is empty,false
otherwise. - #equals?(other : Indexable, &) : Bool
- #equals?(other, &)
Determines if
self
equals other according to a comparison done by the given block. - #fetch(index : Int, &)
Returns the element at the given index, if in bounds, otherwise executes the given block with the index and returns its value.
- #fetch(index, default)
Returns the value at the index given by index, or when not found the value given by default.
- #first(&)
:inherited:
- #hash(hasher)
- #index(object, offset : Int = 0)
Returns the index of the first appearance of value in
self
starting from the given offset, ornil
if the value is not inself
. - #index(offset : Int = 0, & : T -> )
Returns the index of the first object in
self
for which the block returnstrue
, starting from the given offset, ornil
if no match is found. - #join(separator : String | Char | Number = "") : String
Optimized version of
Enumerable#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. - #last : T
Returns the last element of
self
if it's not empty, or raisesIndexError
. - #last(&)
Returns the last element of
self
if it's not empty, or the given block's value. - #last? : T?
Returns the last element of
self
if it's not empty, ornil
. - #permutations(size : Int = self.size) : Array(Array(T))
Returns an
Array
with all possible permutations of size. - #repeated_combinations(size : Int = self.size) : Array(Array(T))
- #reverse_each(& : T -> ) : Nil
Same as
#each
, but works in reverse. - #reverse_each
Returns an
Iterator
over the elements ofself
in reverse order. - #rindex(value, offset = size - 1)
Returns the index of the last appearance of value in
self
, ornil
if the value is not inself
. - #rindex(offset = size - 1, & : T -> )
Returns the index of the first object in
self
for which the block returnstrue
, starting from the last object, ornil
if no match is found. - #sample(n : Int, random = Random::DEFAULT) : Array(T)
Returns an
Array
of n random elements fromself
, using the given random number generator. - #sample(random = Random::DEFAULT)
Optimized version of
Enumerable#sample
that runs in O(1) time. - #size
Returns the number of elements in this container.
- #to_a : Array(T)
Returns an
Array
with all the elements in the collection. - #unsafe_fetch(index : Int)
Returns the element at the given index, without doing any bounds check.
- #values_at(*indexes : Int)
Returns a
Tuple
populated with the elements at the given indexes.
Instance methods inherited from module Enumerable(T)
accumulate(initial : U) : Array(U) forall Uaccumulate : 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_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, first(&)
first(count : Int) : Array(T)
first : T first, first? : T? 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, includes?(obj) : Bool includes?, 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 : T max, max? : T? max?, max_by(& : T -> U) : T forall U max_by, max_by?(& : T -> U) : T? forall U max_by?, max_of(& : T -> U) : U forall U max_of, max_of?(& : T -> U) : U? forall U max_of?, min : T min, min? : T? min?, min_by(& : T -> U) : T forall U min_by, min_by?(& : T -> U) : T? forall U min_by?, min_of(& : T -> U) : U forall U min_of, min_of?(& : T -> U) : U? forall U min_of?, minmax : Tuple(T, T) minmax, minmax? : Tuple(T?, T?) 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, 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::DEFAULT) : Array(T)
sample(random = Random::DEFAULT) : 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(T, Int32) tally, tally_by(& : T -> U) : Hash(U, Int32) forall U tally_by, to_a to_a, to_h
to_h(& : T -> Tuple(K, V)) forall K, V to_h, to_set : Set(T) 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_slice(count : Int, reuse = false) each_slice, 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))Source
Returns an Array
of all ordered combinations of elements taken from each of the indexables as Array
s. Traversal of elements starts from the last Indexable
. If indexables is empty, the returned product contains exactly one empty Array
.
#cartesian_product
is preferred over this class method when the quantity of indexables 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, &)Source
Yields each ordered combination of the elements taken from each of the indexables as Array
s. Traversal of elements starts from the last Indexable
. If indexables is empty, yields an empty Array
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 new Array
is created and yielded for each combination.
- If reuse is an
Array
, it will be reused - If reuse is truthy, the method will create a new
Array
and reuse it - If reuse is falsey, no
Array
s 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)Source
Returns an iterator that enumerates the ordered combinations of elements taken from the indexables as Array
s. Traversal of elements starts from the last Indexable
. If indexables is empty, the returned iterator produces one empty Array
, 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 new Array
is created and returned for each combination.
- If reuse is an
Array
, it will be reused - If reuse is truthy, the method will create a new
Array
and reuse it - If reuse is falsey, no
Array
s 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)Source
Returns the element at the given index.
Negative indices can be used to start counting from the end of the array. Raises IndexError
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)Source
Returns the element at the given index.
Negative indices can be used to start counting from the end of the array. Returns nil
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 -> _)Source
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.
Returns nil
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 -> _)Source
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.
Returns nil
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)Source
Returns an Array
of all ordered combinations of elements taken from each of self
and others as Tuple
s. Traversal of elements starts from the last Indexable
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 dig(index : Int, *subindexes)Source
Traverses the depth of a structure and returns the value, otherwise raises IndexError
.
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)Source
Traverses the depth of a structure and returns the value. Returns nil
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 -> )Source
Calls the given block once for each element in self
, passing that element as a parameter.
a = ["a", "b", "c"] a.each { |x| print x, " -- " }
produces:
a -- b -- c --
def eachSource
Returns an Iterator
for the elements of self
.
a = ["a", "b", "c"] iter = a.each iter.next # => "a" iter.next # => "b"
The returned iterator keeps a reference to self
: if the array changes, the returned values of the iterator change as well.
def each(*, start : Int, count : Int, & : T -> )Source
Calls the given block once for count
number of elements in self
starting from index start
, passing each element as a parameter.
Negative indices count backward from the end of the array. (-1 is the last element).
Raises IndexError
if the starting index is out of range. Raises ArgumentError
if count
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 -> )Source
Calls the given block once for all elements at indices within the given range
, passing each element as a parameter.
Raises IndexError
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)Source
Returns an iterator that enumerates the ordered combinations of elements taken from each of self
and others as Tuple
s. Traversal of elements starts from the last Indexable
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_index(& : Int32 -> ) : NilSource
Calls the given block once for each index in self
, passing that index as a parameter.
a = ["a", "b", "c"] a.each_index { |x| print x, " -- " }
produces:
0 -- 1 -- 2 --
def each_indexSource
Returns an Iterator
for each index in self
.
a = ["a", "b", "c"] iter = a.each_index iter.next # => 0 iter.next # => 1
The returned iterator keeps a reference to self
. If the array changes, the returned values of the iterator will change as well.
def each_index(*, start : Int, count : Int, &)Source
Calls the given block once for count
number of indices in self
starting from index start
, passing each index as a parameter.
Negative indices count backward from the end of the array. (-1 is the last element).
Raises IndexError
if the starting index is out of range. Raises ArgumentError
if count
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, &) : NilSource
Yields each possible permutation of size of self
.
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. If reuse is given, the array can be reused: if reuse is an Array
, this array will be reused; if reuse 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)Source
Returns an Iterator
over each possible permutation of size of self
.
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. If reuse is given, the array can be reused: if reuse is an Array
, this array will be reused; if reuse 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? : BoolSource
Returns true
if self
is empty, false
otherwise.
([] of Int32).empty? # => true ([1]).empty? # => false
def equals?(other, &)Source
Determines if self
equals other according to a comparison done by the given block.
If self
's size is the same as other's size, this method yields elements from self
and other in tandem: if the block returns true for all of them, this method returns true
. Otherwise it returns false
.
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, &)Source
Returns the element at the given index, 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)Source
Returns the value at the index given by index, or when not found the value given by default.
a = [:foo, :bar] a.fetch(0, :default_value) # => :foo a.fetch(2, :default_value) # => :default_value
def first(&)Source
:inherited:
def hash(hasher)Source
def index(object, offset : Int = 0)Source
Returns the index of the first appearance of value in self
starting from the given offset, or nil
if the value is not in self
.
[1, 2, 3, 1, 2, 3].index(2, offset: 2) # => 4
def index(offset : Int = 0, & : T -> )Source
Returns the index of the first object in self
for which the block returns true
, starting from the given offset, or nil
if no match is found.
[1, 2, 3, 1, 2, 3].index(offset: 2) { |x| x < 2 } # => 3
def join(separator : String | Char | Number = "") : StringSource
Optimized version of Enumerable#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 : TSource
Returns the last element of self
if it's not empty, or raises IndexError
.
([1, 2, 3]).last # => 3 ([] of Int32).last # raises IndexError
def last(&)Source
Returns the last element of self
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?Source
Returns the last element of self
if it's not empty, or nil
.
([1, 2, 3]).last? # => 3 ([] of Int32).last? # => nil
def permutations(size : Int = self.size) : Array(Array(T))Source
Returns an Array
with all possible permutations of size.
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 rindex(value, offset = size - 1)Source
Returns the index of the last appearance of value in self
, or nil
if the value is not in self
.
If offset is given, it defines the position to end 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 -> )Source
Returns the index of the first object in self
for which the block returns true
, starting from the last object, or nil
if no match is found.
If offset is given, the search starts from that index towards the first elements in self
.
[1, 2, 3, 2, 3].rindex { |x| x < 3 } # => 3 [1, 2, 3, 2, 3].rindex(offset: 2) { |x| x < 3 } # => 1
def sample(n : Int, random = Random::DEFAULT) : Array(T)Source
Returns an Array
of n random elements from self
, using the given random number generator. All elements have equal probability of being drawn. Sampling is done without replacement; if n is larger than the size of this collection, the returned Array
has the same size as self
.
Raises ArgumentError
if n is negative.
[1, 2, 3, 4, 5].sample(2) # => [3, 5] {1, 2, 3, 4, 5}.sample(2) # => [3, 4] {1, 2, 3, 4, 5}.sample(2, Random.new(1)) # => [1, 5]
If self
is not empty and n
is equal to 1, calls #sample(random)
exactly once. Thus, random will be left in a different state compared to the implementation in Enumerable
.
def sample(random = Random::DEFAULT)Source
Optimized version of Enumerable#sample
that runs in O(1) time.
a = [1, 2, 3] a.sample # => 3 a.sample # => 1 a.sample(Random.new(1)) # => 2
abstract def sizeSource
Returns the number of elements in this container.
def to_a : Array(T)Source
Returns an Array
with all the elements in the collection.
{1, 2, 3}.to_a # => [1, 2, 3]
abstract def unsafe_fetch(index : Int)Source
Returns the element at the given index, without doing any bounds check.
Indexable
makes sure to invoke this method with index in 0...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)Source
Returns a Tuple
populated with the elements at the given indexes. Raises IndexError
if any index is invalid.
["a", "b", "c", "d"].values_at(0, 2) # => {"a", "c"}
© 2012–2021 Manas Technology Solutions.
Licensed under the Apache License, Version 2.0.
https://crystal-lang.org/api/1.2.1/Indexable.html