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

indexable.cr

## Instance Method Detail

def [](index : Int) #

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  # => 'a'
ary  # => 'c'
ary[-1] # => 'c'
ary[-2] # => 'b'

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

def []?(index : Int) #

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?  # => 'a'
ary?  # => 'c'
ary[-1]? # => 'c'
ary[-2]? # => 'b'

ary?  # nil
ary[-4]? # nil``````

def bsearch(&block : T -> Bool) #

By using binary search, returns the first element for which the passed block returns `true`.

If the block returns `false`, the finding element exists behind. If the block returns `true`, the finding element is itself or exists in front.

Binary search needs sorted array, so `self` has to be sorted.

Returns `nil` if the block didn't return `true` for any element.

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

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

By using binary search, returns the index of the first element for which the passed block returns `true`.

If the block returns `false`, the finding element exists behind. If the block returns `true`, the finding element is itself or exists in front.

Binary search needs sorted array, so `self` has to be sorted.

Returns `nil` if the block didn't return `true` 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 combinations(size : Int = self.size) #

def dig(index : Int, *subindexes) #

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

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(&) #

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

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, &) #

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, &) #

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_combination(size : Int = self.size, reuse = false, &) : Nil #

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

def each_index(&) : Nil #

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

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, &) #

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, &) : Nil #

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

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 each_repeated_combination(size : Int = self.size, reuse = false, &) : Nil #

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

def empty? : Bool #

Returns `true` if `self` is empty, `false` otherwise.

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

def equals?(other : Indexable, &) #

Optimized version of `#equals?` used when `other` is also an `Indexable`.

def equals?(other, &) #

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, &) #

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

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(&) #

:inherited:

def hash(hasher) #

See `Object#hash(hasher)`

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

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, &) #

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 = "") : 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.

def last : T #

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(&) #

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

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

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

def reverse_each(&) : Nil #

Same as `#each`, but works in reverse.

def reverse_each #

Returns an `Iterator` over the elements of `self` in reverse order.

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

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, &) #

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(random = Random::DEFAULT) #

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

Returns the number of elements in this container.

def to_a : Array(T) #

Returns an `Array` with all the elements in the collection.

``{1, 2, 3}.to_a # => [1, 2, 3]``

abstract def unsafe_fetch(index : Int) #

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

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