std.array.Array
type pub Array[T]
An ordered, integer-indexed generic collection of values.
Accessing values in an Array
is a constant-time operation.
Arrays are created using the array literal syntax, instead of using a method. Here's how you'd create an empty Array:
[]
And here's how you'd create an Array with values:
[10, 20, 30]
All values in an array must be of the same type, and the array's value type is based on the type of the first value.
Static methods
filled
Show source codeHide source code
fn pub static filled[V: Clone](with: move V, times: Int) -> Array[move V] {
if times == 0 { return [] }
let array = with_capacity(times)
let temp = ref with
(times - 1).times(fn (_) { array.push(temp.clone) })
array.push(with)
array
}
fn pub static filled[V: Clone](with: move V, times: Int) -> Array[move V]
Returns an array filled with a certain amount of values.
The times
argument specifies how many times the with
argument must
exist in the array.
Examples
Array.filled(with: 0, times: 4) # => [0, 0, 0, 0]
with_capacity
Show source codeHide source code
fn pub static with_capacity(size: Int) -> Array[T] {
if size < 0 { invalid_capacity(size) }
Array(size: 0, capacity: size, buffer: alloc.resize(0 as Pointer[T], size))
}
fn pub static with_capacity(size: Int) -> Array[T]
Returns a new Array
with enough space for at least size
values.
Panics
This method panics of size
if less than zero.
Instance methods
!=
Show source codeHide source code
fn pub !=(other: ref Self) -> Bool {
(self == other).false?
}
fn pub !=(other: ref Self) -> Bool
if
T: Equal
Returns true
if self
and the given object are not equal to each other.
==
Show source codeHide source code
fn pub ==(other: ref Array[T]) -> Bool {
if @size != other.size { return false }
let mut index = 0
let max = @size
while index < max {
let ours = get(index)
let theirs = other.get(index)
if ours != theirs { return false }
index += 1
}
true
}
fn pub ==(other: ref Array[T]) -> Bool
if
T: Equal
Returns true
if self
and the given Array
are identical.
Examples
Comparing two identical arrays:
[10, 20, 30] == [10, 20, 30] # => true
Comparing two arrays with a different size:
[10] == [10, 20] # => false
Comparing two arrays with the same size but with different values:
[10, 20] == [20, 10] # => false
append
Show source codeHide source code
fn pub mut append(other: Array[T]) {
let len = other.size
if len == 0 { return }
reserve_exact(len)
let tail = ptr.add(@buffer, @size)
alloc.copy(other.pointer, tail, len)
@size += len
# This is necessary such that when `other` is dropped, we don't drop the
# values that have been moved into `self`.
other.size = 0
}
fn pub mut append(other: Array[T])
Appends the values of the given Array
to self
.
Examples
Appending one Array
to another:
let numbers = [10, 20, 30]
numbers.append([40, 50])
numbers.size # => 5
capacity
Show source codeHide source code
fn pub capacity -> Int {
@capacity
}
fn pub capacity -> Int
Returns the number of values that can be stored in self
before self
needs to be resized.
Examples
Array.with_capacity(2).capacity # => 2
clear
Show source codeHide source code
fn pub mut clear {
let mut index = 0
let max = @size
while index < max { read_from(index := index + 1) }
@size = 0
}
fn pub mut clear
Removes all values in the Array.
Examples
let array = [10, 20, 30]
array.clear
array.empty? # => true
clone
Show source codeHide source code
fn pub clone -> Array[move T] {
let len = @size
let new = Array.with_capacity(len)
let mut index = 0
while index < len { new.push(get_unchecked(index := index + 1).clone) }
new
}
fn pub clone -> Array[move T]
if
T: Clone
Creates a clone of self
.
The returned value is an owned value that is the same type as the receiver
of this method. For example, cloning a ref Array[Int]
results in a
Array[Int]
, not another ref Array[Int]
.
contains?
Show source codeHide source code
fn pub contains?(value: ref T) -> Bool {
iter.any?(fn (ours) { ours == value })
}
fn pub contains?(value: ref T) -> Bool
if
T: Equal
Returns true
if self
contains the given value.
Examples
[10, 20, 30].contains?(10) # => true
empty?
Show source codeHide source code
fn pub empty? -> Bool {
@size == 0
}
fn pub empty? -> Bool
Returns true
if self
is empty.
Examples
[10].empty? # => false
[].empty? # => true
fmt
Show source codeHide source code
fn pub fmt(formatter: mut Formatter) {
let fmt = formatter.array
for value in iter { fmt.value(value) }
fmt.finish
}
fn pub fmt(formatter: mut Formatter)
if
T: Format
Formats self
in a human-readable format for debugging purposes.
get
Show source codeHide source code
fn pub inline get(index: Int) -> Result[ref T, OutOfBounds] {
try check_bounds(index, @size)
Result.Ok(get_unchecked(index))
}
fn pub inline get(index: Int) -> Result[ref T, OutOfBounds]
Returns an immutable borrow of the value at the given index.
If the index is out of bounds, a std.bounds.OutOfBounds
error is returned.
Examples
let numbers = [10, 20]
numbers.get(0) # => Result.Ok(10)
numbers.get(10) # => Result.Error(OutOfBounds(...))
get_mut
Show source codeHide source code
fn pub inline mut get_mut(index: Int) -> Result[mut T, OutOfBounds] {
try check_bounds(index, @size)
Result.Ok(get_unchecked_mut(index))
}
fn pub inline mut get_mut(index: Int) -> Result[mut T: mut, OutOfBounds]
if
T: mut
Returns a mutable borrow of the value at the given index.
If the index is out of bounds, a std.bounds.OutOfBounds
error is returned.
Examples
let numbers = [10, 20]
numbers.get_mut(0) # => Result.Ok(10)
numbers.get_mut(10) # => Result.Error(OutOfBounds(...))
hash
Show source codeHide source code
fn pub hash[H: mut + Hasher](hasher: mut H) {
let mut index = 0
let len = @size
while index < len { get_unchecked(index := index + 1).hash(hasher) }
}
fn pub hash[H: mut + Hasher](hasher: mut H: mut)
if
T: Hash
Writes the hash for self
into the given Hasher
.
index_of
Show source codeHide source code
fn pub index_of(value: ref T) -> Option[Int] {
let mut idx = 0
while idx < @size {
if get_unchecked(idx) == value { return Option.Some(idx) }
idx += 1
}
Option.None
}
fn pub index_of(value: ref T) -> Option[Int]
if
T: Equal
Returns the index of value
as a Some
if present, otherwise it returns a
None
.
Examples
[10, 20, 30].index_of(20) # => Option.Some(1)
[10, 20, 30].index_of(50) # => Option.None
insert
Show source codeHide source code
fn pub mut insert(index: Int, value: T) {
if index < 0 or index > @size {
panic(OutOfBounds.new(index, @size).to_string)
}
reserve(1)
# Shift to the right if the insertion isn't at the end of the array. If we
# have values like this:
#
# [A, B, C, D]
#
# And we want to insert at the index of B (index 1), this results in the
# following values:
#
# [A, B, B, C, D]
#
# We can then overwrite index 1 with the value to insert.
if index < @size {
let from = address_of(index)
let to = address_of(index + 1)
alloc.copy(from, to, size: @size - index)
}
write_to(index, value)
@size += 1
}
fn pub mut insert(index: Int, value: T)
Inserts the value at the given index, shifting all values after it to the right.
Panics
This method panics if index
is out of bounds.
Examples
Inserting a value at the start:
let nums = [10, 20]
nums.insert(0, 30)
nums # => [30, 10, 20]
Inserting a value at the end:
let nums = [10, 20]
nums.insert(2, 30)
nums # => [10, 20, 30]
into_iter
Show source codeHide source code
fn pub move into_iter -> IntoIter[T] {
IntoIter(array: self, index: 0)
}
fn pub move into_iter -> IntoIter[T]
Returns an iterator that moves the values out of self
.
Examples
let numbers = [10, 20, 30]
let iter = numbers.into_iter
iter.next # => Option.Some(10)
iter.next # => Option.Some(20)
iter.next # => Option.Some(30)
iter.next # => Option.None
iter
Show source codeHide source code
fn pub iter -> Stream[ref T] {
let mut idx = 0
Stream.new(fn move {
if idx < @size {
Option.Some(get_unchecked(idx := idx + 1))
} else {
Option.None
}
})
}
fn pub iter -> Stream[ref T]
Returns an iterator that yields immutable references to the values in
self
.
iter_mut
Show source codeHide source code
fn pub mut iter_mut -> Stream[mut T] {
let mut idx = 0
Stream.new(fn move {
if idx < @size {
Option.Some(get_unchecked_mut(idx := idx + 1))
} else {
Option.None
}
})
}
fn pub mut iter_mut -> Stream[mut T: mut]
if
T: mut
Returns an iterator that yields mutable references to the values in self
.
last
Show source codeHide source code
fn pub last -> Option[ref T] {
get(size - 1).ok
}
fn pub last -> Option[ref T]
Returns an immutable reference to the last value in self
.
Examples
[].last # => Option.None
[10, 20].last # => Option.Some(20)
last_mut
Show source codeHide source code
fn pub mut last_mut -> Option[mut T] {
get_mut(size - 1).ok
}
fn pub mut last_mut -> Option[mut T: mut]
if
T: mut
Returns a mutable reference to the last value in self
.
Examples
[].last_mut # => Option.None
[10, 20].last_mut # => Option.Some(20)
pop
Show source codeHide source code
fn pub mut pop -> Option[T] {
if @size == 0 { return Option.None }
@size -= 1
Option.Some(read_from(@size))
}
fn pub mut pop -> Option[T]
Removes a value from the back of the Array, returning the removed value.
If no value was found, a None is returned instead.
Examples
Popping an existing value:
let array = [10]
array.pop # => Option.Some(10)
array.empty? # => true
Popping a value when the Array is empty:
let array = []
array.pop # => Option.None
push
Show source codeHide source code
fn pub mut push(value: T) {
reserve(1)
write_to(@size, value)
@size += 1
}
fn pub mut push(value: T)
Pushes a value to the back of the Array.
Examples
Pushing a value into an Array:
let array = []
array.push(10) # => Nil
array.get(0) # => 10
remove_at
Show source codeHide source code
fn pub mut remove_at(index: Int) -> Result[T, OutOfBounds] {
let len = size
try check_bounds(index, len)
let addr = address_of(index)
let val = addr.0
alloc.copy(from: ptr.add(addr, 1), to: addr, size: len - index - 1)
@size = len - 1
Result.Ok(val)
}
fn pub mut remove_at(index: Int) -> Result[T, OutOfBounds]
Removes the value at the given index, returning the removed value.
Values to the right of the index are shifted to the left.
If the index is out of bounds, a std.bounds.OutOfBounds
error is returned.
Examples
Removing an existing value will result in the value being removed from the Array and returned:
let array = [10]
array.remove_at(0) # => Result.Ok(10)
array.empty? # => true
remove_if
Show source codeHide source code
fn pub mut remove_if(condition: fn (ref T) -> Bool) {
let mut idx = 0
while idx < @size {
if condition.call(get_unchecked(idx)) {
let addr = address_of(idx)
drop_value(addr.0)
alloc.copy(from: ptr.add(addr, 1), to: addr, size: @size - idx - 1)
@size -= 1
# Because we shift to the left, we need to visit the current index
# again, otherwise we'd miss the value that came after it _before_ the
# shift.
} else {
idx += 1
}
}
}
fn pub mut remove_if(condition: fn (ref T) -> Bool)
Removes all values for which the condition
closure returns true
.
This method shifts values to the left every time a value is removed. When
removing many values from an Array
, it's likely more efficient to create a
new Array
and copy/move the values to keep to this new Array
.
Examples
let vals = [10, 20, 30, 40, 50]
vals.remove_if(fn (v) { v <= 30 })
vals # => [40, 50]
reserve
Show source codeHide source code
fn pub mut reserve(size: Int) {
if @capacity - @size >= size { return }
@capacity = max(@capacity * 2, @capacity + size)
@buffer = alloc.resize(@buffer, @capacity)
}
fn pub mut reserve(size: Int)
Reserves space for size
additional values.
The actual space reserved may be greater to prevent frequent reallocations.
After calling this method, the capacity will be greater than or equal to
self.size + size
.
If the capacity is great enough or the given size is less than zero, this method does nothing.
reserve_exact
Show source codeHide source code
fn pub mut reserve_exact(size: Int) {
if @capacity - @size >= size { return }
@capacity = @capacity + size
@buffer = alloc.resize(@buffer, @capacity)
}
fn pub mut reserve_exact(size: Int)
Reserves space for exactly size
additional values.
Unlike Array.reserve
, this method won't allocate more than the given
amount.
If there's already enough space for size
extra values, this method does
nothing.
reverse
Show source codeHide source code
fn pub mut reverse {
let mut a = 0
let mut b = @size - 1
while a < b {
let a_val = read_from(a)
let b_val = read_from(b)
write_to(b, a_val)
write_to(a, b_val)
a += 1
b -= 1
}
}
fn pub mut reverse
Reverses self
in-place
Examples
let a = [10, 20, 30]
a.reverse
a # => [30, 20, 10]
reverse_iter
Show source codeHide source code
fn pub reverse_iter -> Stream[ref T] {
let mut index = size - 1
Stream.new(fn move {
if index > -1 { get(index := index - 1).ok } else { Option.None }
})
}
fn pub reverse_iter -> Stream[ref T]
Returns an Iter
that iterates over all values in self
in reverse
order.
Examples
Iterating over an Array
in reverse order:
let numbers = [10, 20, 30]
let iter = numbers.reverse_iter
iter.next # => Option.Some(30)
iter.next # => Option.Some(20)
iter.next # => Option.Some(10)
iter.next # => Option.None
set
Show source codeHide source code
fn pub mut set(index: Int, value: T) {
check_bounds(index, @size).or_panic
drop_value(read_from(index))
write_to(index, value)
}
fn pub mut set(index: Int, value: T)
Stores a value at the given index.
If a value is already present at the given index, it's dropped before the new value overwrites it.
Panics
This method panics if the index is out of bounds.
Examples
let array = []
array.set(0, 10)
array # => [10]
shuffle
Show source codeHide source code
fn pub mut shuffle(rng: mut Random) {
let mut swap = size - 1
while swap > 0 {
swap_indexes(swap, with: rng.int_between(min: 0, max: swap))
swap -= 1
}
}
fn pub mut shuffle(rng: mut Random)
Sorts the values in self
such that they are in a random order.
The algorithm used by this method is Sattolo's algorithm. Some more details on this are found here:
- https://en.wikipedia.org/wiki/Fisher–Yates_shuffle#Sattolo's_algorithm
- https://danluu.com/sattolo/
- https://rosettacode.org/wiki/Sattolo_cycle
Examples
import std.rand (Random)
let rng = Random.new
let nums = [10, 20]
nums.shuffle(rng)
nums # => [20, 10]
size
Show source codeHide source code
fn pub size -> Int {
@size
}
fn pub size -> Int
Returns the number of values in self
.
Examples
Getting the size of an empty Array:
[].size # => 0
Getting the size of an Array with values:
[10].size # => 1
sort
Show source codeHide source code
fn pub mut sort {
stable_sort(self, fn (a, b) { a <= b })
}
fn pub mut sort
if
T: Compare
Sorts the values in self
in ascending order.
This method performs a stable sort, meaning it maintains the relative order of duplicate values.
Examples
let nums = [0, 3, 3, 5, 9, 1]
nums.sort
nums # => [0, 1, 3, 3, 5, 9]
sort_by
Show source codeHide source code
fn pub mut sort_by(block: fn (ref T, ref T) -> Ordering) {
stable_sort(self, fn (a, b) {
match block.call(a, b) {
case Less or Equal -> true
case _ -> false
}
})
}
fn pub mut sort_by(block: fn (ref T, ref T) -> Ordering)
Sorts the values in self
using a custom comparison closure.
Like Array.sort
, this method performs a stable sort.
Examples
let nums = [0, 3, 3, 5, 9, 1]
nums.sort_by fn (a, b) { b.cmp(a) }
nums # => [9, 5, 3, 3, 1, 0]
swap
Show source codeHide source code
fn pub mut swap(index: Int, with: T) -> T {
check_bounds(index, @size).or_panic
let old = read_from(index)
write_to(index, with)
old
}
fn pub mut swap(index: Int, with: T) -> T
Inserts the value at the given index, returning the old value.
Panics
This method panics if the index is out of bounds.
Examples
let numbers = [10, 20, 30]
numbers.swap(index: 1, with: 40) # => 20
numbers # => [10, 40, 30]
swap_indexes
Show source codeHide source code
fn pub mut swap_indexes(index: Int, with: Int) {
check_bounds(index, @size).or_panic
check_bounds(with, @size).or_panic
let a = read_from(index)
let b = read_from(with)
write_to(index, b)
write_to(with, a)
}
fn pub mut swap_indexes(index: Int, with: Int)
Swaps the values at the given indexes.
Panics
This method panics if index
or with
is out of bounds.
Examples
let numbers = [10, 20, 30]
numbers.swap_indexes(index: 0, with: 2)
numbers # => [30, 20, 10]
Implemented traits
Clone
impl Clone for Array
if
T: Clone
Equal
impl Equal for Array
if
T: Equal
Drop
impl Drop for Array
Format
impl Format for Array
if
T: Format
Hash
impl Hash for Array
if
T: Hash