Indexable::Mutable(T) - Crystal 1.16.3

# module Indexable::Mutable(T)

##
Overview

An `Indexable` container that is additionally mutable.

Including types may write values to numeric indices, apart from reading them. This module does not cover cases where the container is resized.

##
Included Modules

- Indexable(T)

##
Direct including types

- Array(T)
- BitArray
- Deque(T)
- Slice(T)
- StaticArray(T, N)

##
Defined in:

indexable/mutable.cr

##
Instance Method Summary

- #[]=(index : Int, value : T) : T

  Sets the given value at the given index.

- #fill(value : T, start : Int, count : Int) : self

  Replaces count or less (if there aren't enough) elements starting at the given start index with value.

- #fill(value : T, range : Range) : self

  Replaces the elements within the given range with value.

- #fill(value : T) : self

  Replaces every element in `self` with the given value.

- #fill(start : Int, count : Int, & : Int32 -> T) : self

  Yields each index of `self`, starting at start and for count times (or less if there aren't enough elements), to the given block and then assigns the block's value in that position.

- #fill(range : Range, & : Int32 -> T) : self

  Yields each index of `self`, in the given range, to the given block and then assigns the block's value in that position.

- #fill(*, offset : Int = 0, & : Int32 -> T) : self

  Yields each index of `self` to the given block and then assigns the block's value in that position.

- #map!(& : T -> _) : self

  Invokes the given block for each element of `self`, replacing the element with the value returned by the block.

- #map_with_index!(offset = 0, & : T, Int32 -> _) : self

  Like `#map!`, but the block gets passed both the element and its index.

- #reverse! : self

  Reverses in-place all the elements of `self`.

- #rotate!(n : Int = 1) : self

  Shifts all elements of `self` to the left n times.

- #shuffle!(random : Random = Random::DEFAULT) : self

  Modifies `self` by randomizing the order of elements in the collection using the given random number generator.

- #sort! : self

  Sorts all elements in `self` based on the return value of the comparison method `T#<=>` (see `Comparable#<=>`), using a stable sort algorithm.

- #sort!(&block : T, T -> U) : self forall U

  Sorts all elements in `self` based on the comparator in the given block, using a stable sort algorithm.

- #sort_by!(&block : T -> _) : self

  Sorts all elements in `self` by the output value of the block.

- #swap(index0 : Int, index1 : Int) : self

  Swaps the elements at index0 and index1.

- #unsafe_put(index : Int, value : T)

  Sets the element at the given index to value, without doing any bounds check.

- #unstable_sort! : self

  Sorts all elements in `self` based on the return value of the comparison method `T#<=>` (see `Comparable#<=>`), using an unstable sort algorithm.

- #unstable_sort!(&block : T, T -> U) : self forall U

  Sorts all elements in `self` based on the comparator in the given block, using an unstable sort algorithm.

- #unstable_sort_by!(&block : T -> _) : self

  Sorts all elements in `self` by the output value of the block.

- #update(index : Int, & : T -> _) : T

  Yields the current element at the given index and updates the value at that index with the block's value.

### Instance methods inherited from module `Indexable(T)`

[](index : Int) [], []?(index : Int) []?, bsearch(& : T -> _) bsearch, bsearch_index(& : T, Int32 -> _) bsearch_index, cartesian_product(*others : Indexable) cartesian_product, combinations(size : Int = self.size) combinations, dig(index : Int, *subindexes) dig, dig?(index : Int, *subindexes) dig?, each(& : T -> )
each
each(*, start : Int, count : Int, & : T -> )
each(*, within range : Range, & : T -> ) each, each_cartesian(*others : Indexable, &)
each_cartesian(*others : Indexable) each_cartesian, each_combination(size : Int = self.size, reuse = false, &) : Nil
each_combination(size : Int = self.size, reuse = false) each_combination, each_index(& : Int32 -> ) : Nil
each_index
each_index(*, start : Int, count : Int, &) each_index, each_permutation(size : Int = self.size, reuse = false, &) : Nil
each_permutation(size : Int = self.size, reuse = false) each_permutation, each_repeated_combination(size : Int = self.size, reuse = false, &) : Nil
each_repeated_combination(size : Int = self.size, reuse = false) each_repeated_combination, empty? : Bool empty?, equals?(other : Indexable, &) : Bool
equals?(other, &) equals?, fetch(index : Int, &)
fetch(index, default) fetch, find(if_none = nil, offset : Int = 0, & : T -> ) find, find!(offset : Int = 0, & : T -> ) find!, first(&) first, hash(hasher) hash, index(object, offset : Int = 0)
index(offset : Int = 0, & : T -> ) index, index!(obj, offset : Int = 0)
index!(offset : Int = 0, & : T -> ) index!, join(separator : String | Char | Number = "") : String join, last : T
last(&) last, last? : T | Nil last?, permutations(size : Int = self.size) : Array(Array(T)) permutations, repeated_combinations(size : Int = self.size) : Array(Array(T)) repeated_combinations, reverse_each(& : T -> ) : Nil
reverse_each reverse_each, rindex(value, offset = size - 1)
rindex(offset = size - 1, & : T -> ) rindex, rindex!(value, offset = size - 1)
rindex!(offset = size - 1, & : T -> ) rindex!, sample(n : Int, random : Random = Random::DEFAULT) : Array(T)
sample(random : Random = Random::DEFAULT) sample, size size, to_a(& : T -> U) : Array(U) forall U to_a, unsafe_fetch(index : Int) unsafe_fetch, values_at(*indexes : Int) values_at

### Class methods inherited from module `Indexable(T)`

cartesian_product(indexables : Indexable(Indexable)) cartesian_product, each_cartesian(indexables : Indexable(Indexable), reuse = false, &)
each_cartesian(indexables : Indexable(Indexable), reuse = false) each_cartesian

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

##
Instance Method Detail

def []=(index : Int, value : T) : T #

Sets the given value at the given index. Returns value.

Negative indices can be used to start counting from the end of the container. Raises `IndexError` if trying to set an element outside the container's range.

    ary = [1, 2, 3]
    ary[0] = 5
    ary # => [5, 2, 3]

    ary[3] = 5 # raises IndexError

def fill(value : T, start : Int, count : Int) : self #

Replaces count or less (if there aren't enough) elements starting at the given start index with value. Returns `self`.

Negative values of start count from the end of the container.

Raises `IndexError` if the start index is out of range.

Raises `ArgumentError` if count is negative.

    array = [1, 2, 3, 4, 5]
    array.fill(9, 2, 2) # => [1, 2, 9, 9, 5]
    array               # => [1, 2, 9, 9, 5]

def fill(value : T, range : Range) : self #

Replaces the elements within the given range with value. Returns `self`.

Negative indices count backward from the end of the container.

Raises `IndexError` if the starting index is out of range.

    array = [1, 2, 3, 4, 5]
    array.fill(9, 2..3) # => [1, 2, 9, 9, 5]
    array               # => [1, 2, 9, 9, 5]

def fill(value : T) : self #

Replaces every element in `self` with the given value. Returns `self`.

    array = [1, 2, 3, 4]
    array.fill(2) # => [2, 2, 2, 2]
    array         # => [2, 2, 2, 2]

def fill(start : Int, count : Int, & : Int32 -> T) : self #

Yields each index of `self`, starting at start and for count times (or less if there aren't enough elements), to the given block and then assigns the block's value in that position. Returns `self`.

Negative values of start count from the end of the container.

Has no effect if count is zero or negative.

Raises `IndexError` if start is outside the array range.

    a = [1, 2, 3, 4, 5, 6]
    a.fill(2, 3) { |i| i * i * i } # => [1, 2, 8, 27, 64, 6]

def fill(range : Range, & : Int32 -> T) : self #

Yields each index of `self`, in the given range, to the given block and then assigns the block's value in that position. Returns `self`.

Negative indices count backward from the end of the container.

Raises `IndexError` if the starting index is out of range.

    a = [1, 2, 3, 4, 5, 6]
    a.fill(2..4) { |i| i * i * i } # => [1, 2, 8, 27, 64, 6]

def fill(*, offset : Int = 0, & : Int32 -> T) : self #

Yields each index of `self` to the given block and then assigns the block's value in that position. Returns `self`.

Accepts an optional offset parameter, which tells the block to start counting from there.

    array = [2, 1, 1, 1]
    array.fill { |i| i * i }            # => [0, 1, 4, 9]
    array                               # => [0, 1, 4, 9]
    array.fill(offset: 3) { |i| i * i } # => [9, 16, 25, 36]
    array                               # => [9, 16, 25, 36]

def map!(& : T -> _) : self #

Invokes the given block for each element of `self`, replacing the element with the value returned by the block. Returns `self`.

    a = [1, 2, 3]
    a.map! { |x| x * x }
    a # => [1, 4, 9]

def map_with_index!(offset = 0, & : T, Int32 -> _) : self #

Like `#map!`, but the block gets passed both the element and its index.

Accepts an optional offset parameter, which tells it to start counting from there.

    gems = ["crystal", "pearl", "diamond"]
    gems.map_with_index! { |gem, i| "#{i}: #{gem}" }
    gems # => ["0: crystal", "1: pearl", "2: diamond"]

def reverse! : self #

Reverses in-place all the elements of `self`. Returns `self`.

def rotate!(n : Int = 1) : self #

Shifts all elements of `self` to the left n times. Returns `self`.

    a1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    a2 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    a3 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

    a1.rotate!
    a2.rotate!(1)
    a3.rotate!(3)

    a1 # => [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
    a2 # => [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
    a3 # => [3, 4, 5, 6, 7, 8, 9, 0, 1, 2]

def shuffle!(random : Random = Random::DEFAULT) : self #

Modifies `self` by randomizing the order of elements in the collection using the given random number generator. Returns `self`.

    a = [1, 2, 3, 4, 5]
    a.shuffle!(Random.new(42)) # => [3, 2, 4, 5, 1]
    a                          # => [3, 2, 4, 5, 1]

def sort! : self #

Sorts all elements in `self` based on the return value of the comparison method `T#<=>` (see `Comparable#<=>`), using a stable sort algorithm.

    a = [3, 1, 2]
    a.sort!
    a # => [1, 2, 3]

This sort operation modifies `self`. See `#sort` for a non-modifying option that allocates a new instance.

See `Slice#sort!` for details on the implementation.

Raises `ArgumentError` if the comparison between any two elements returns `nil`.

def sort!(&block : T, T -> U) : self forall U #

Sorts all elements in `self` based on the comparator in the given block, using a stable sort algorithm.

The block must implement a comparison between two elements a and b, where `a < b` returns `-1`, `a == b` returns `0`, and `a > b` returns `1`. The comparison operator `<=>` can be used for this.

    a = [3, 1, 2]
    # This is a reverse sort (forward sort would be `a <=> b`)
    a.sort! { |a, b| b <=> a }
    a # => [3, 2, 1]

This sort operation modifies `self`. See `#sort(&block : T, T -> U)` for a non-modifying option that allocates a new instance.

See `Slice#sort!(&block : T, T -> U)` for details on the implementation.

Raises `ArgumentError` if for any two elements the block returns `nil`.

def sort_by!(&block : T -> _) : self #

Sorts all elements in `self` by the output value of the block. The output values are compared via the comparison method `#<=>` (see `Comparable#<=>`), using a stable sort algorithm.

    a = %w(apple pear fig)
    a.sort_by! { |word| word.size }
    a # => ["fig", "pear", "apple"]

This sort operation modifies `self`. See `#sort_by(&block : T -> _)` for a non-modifying option that allocates a new instance.

If stability is expendable, `#unstable_sort_by!(&block : T -> _)` provides a performance advantage over stable sort.

See `#sort!(&block : T -> _)` for details on the sorting mechanism.

Raises `ArgumentError` if the comparison between any two comparison values returns `nil`.

def swap(index0 : Int, index1 : Int) : self #

Swaps the elements at index0 and index1. Returns `self`.

Negative indices can be used to start counting from the end of the container. Raises `IndexError` if either index is out of bounds.

    a = ["first", "second", "third"]
    a.swap(1, 2)  # => ["first", "third", "second"]
    a             # => ["first", "third", "second"]
    a.swap(0, -1) # => ["second", "third", "first"]
    a             # => ["second", "third", "first"]
    a.swap(2, 3)  # raises IndexError

abstract def unsafe_put(index : Int, value : T) #

Sets the element at the given index to value, without doing any bounds check.

`Indexable::Mutable` 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 modify elements with `#[]=(index, value)`.

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 unstable_sort! : self #

Sorts all elements in `self` based on the return value of the comparison method `T#<=>` (see `Comparable#<=>`), using an unstable sort algorithm.

    a = [3, 1, 2]
    a.unstable_sort!
    a # => [1, 2, 3]

This sort operation modifies `self`. See `#unstable_sort` for a non-modifying option that allocates a new instance.

See `Slice#unstable_sort!` for details on the implementation.

Raises `ArgumentError` if the comparison between any two elements returns `nil`.

def unstable_sort!(&block : T, T -> U) : self forall U #

Sorts all elements in `self` based on the comparator in the given block, using an unstable sort algorithm.

The block must implement a comparison between two elements a and b, where `a < b` returns `-1`, `a == b` returns `0`, and `a > b` returns `1`. The comparison operator `<=>` can be used for this.

    a = [3, 1, 2]
    # This is a reverse sort (forward sort would be `a <=> b`)
    a.unstable_sort! { |a, b| b <=> a }
    a # => [3, 2, 1]

This sort operation modifies `self`. See `#unstable_sort(&block : T, T -> U)` for a non-modifying option that allocates a new instance.

See `Slice#unstable_sort!(&block : T, T -> U)` for details on the implementation.

Raises `ArgumentError` if for any two elements the block returns `nil`.

def unstable_sort_by!(&block : T -> _) : self #

Sorts all elements in `self` by the output value of the block. The output values are compared via the comparison method `#<=>` (see `Comparable#<=>`), using an unstable sort algorithm.

    a = %w(apple pear fig)
    a.unstable_sort_by! { |word| word.size }
    a # => ["fig", "pear", "apple"]

This sort operation modifies `self`. See `#unstable_sort_by(&block : T -> _)` for a non-modifying option that allocates a new instance.

If stability is necessary, use `#sort_by!(&block : T -> _)` instead.

See `#unstable_sort!(&block : T -> _)` for details on the sorting mechanism.

Raises `ArgumentError` if the comparison between any two comparison values returns `nil`.

def update(index : Int, & : T -> _) : T #

Yields the current element at the given index and updates the value at that index with the block's value. Returns the new value.

Raises `IndexError` if trying to set an element outside the container's range.

    array = [1, 2, 3]
    array.update(1) { |x| x * 2 } # => 4
    array                         # => [1, 4, 3]
    array.update(5) { |x| x * 2 } # raises IndexError