Mutable array utilities.
public func empty<T>() : [var T]
Creates an empty mutable array (equivalent to [var]
).
public func repeat<T>(item : T, size : Nat) : [var T]
Creates a mutable array containing item
repeated size
times.
motoko include=import
let array = VarArray.repeat<Nat>("Echo", 3);
assert array == [var "Echo", "Echo", "Echo"];
Runtime: O(size)
Space: O(size)
public func clone<T>(array : [var T]) : [var T]
Duplicates array
, returning a shallow copy of the original.
motoko include=import
let array1 = [var 1, 2, 3];
let array2 = VarArray.clone<Nat>(array1);
array2[0] := 0;
assert array1 == [var 1, 2, 3];
assert array2 = [var 0, 2, 3];
Runtime: O(size)
Space: O(size)
public func tabulate<T>(size : Nat, generator : Nat -> T) : [var T]
Creates an immutable array of size size
. Each element at index i
is created by applying generator
to i.
motoko include=import
let array : [var Nat] = VarArray.tabulate<Nat>(4, func i = i * 2);
assert array == [var 0, 2, 4, 6];
Runtime: O(size)
Space: O(size)
*Runtime and space assumes that generator
runs in O(1) time and space.
public func find<T>(array : [var T], predicate : T -> Bool) : ?T
Returns the first value in array
for which predicate
returns true.
If no element satisfies the predicate, returns null.
motoko include=import
let array = [var 1, 9, 4, 8];
VarArray.find<Nat>(array, func x = x > 8)
Runtime: O(size)
Space: O(1)
*Runtime and space assumes that predicate
runs in O(1) time and space.
public func concat<T>(array1 : [var T], array2 : [var T]) : [var T]
Create a new mutable array by concatenating the values of array1
and array2
.
Note that Array.append
copies its arguments and has linear complexity.
motoko include=import
let array1 = [var 1, 2, 3];
let array2 = [var 4, 5, 6];
VarArray.concat<Nat>(array1, array2)
Runtime: O(size1 + size2)
Space: O(size1 + size2)
public func sort<T>(array : [var T], compare : (T, T) -> Order.Order) : [var T]
Sorts the elements in a mutable array according to compare
.
Sort is deterministic and stable.
motoko include=import
import Nat "mo:base/Nat";
let array = [var 4, 2, 6];
VarArray.sort(array, Nat.compare)
Runtime: O(size * log(size))
Space: O(size)
*Runtime and space assumes that compare
runs in O(1) time and space.
public func sortInPlace<T>(array : [var T], compare : (T, T) -> Order.Order) : ()
Sorts the elements in a mutable array in place according to compare
.
Sort is deterministic and stable.
motoko include=import
import Nat "mo:base/Nat";
let array = [var 4, 2, 6];
VarArray.sortInPlace(array, Nat.compare);
assert array == [var 2, 4, 6];
Runtime: O(size * log(size))
Space: O(size)
*Runtime and space assumes that compare
runs in O(1) time and space.
public func reverse<T>(array : [var T]) : [var T]
Creates a new mutable array by reversing the order of elements in array
.
motoko include=import
let array = [var 10, 11, 12];
VarArray.reverse(array)
Runtime: O(size)
Space: O(1)
public func reverseInPlace<T>(array : [var T]) : ()
Reverses the order of elements in a mutable array in place.
motoko include=import
let array = [var 10, 11, 12];
VarArray.reverseInPlace(array);
assert array == [var 12, 11, 10];
Runtime: O(size)
Space: O(1)
public func forEach<T>(array : [var T], f : T -> ())
Calls f
with each element in array
.
Retains original ordering of elements.
motoko include=import
import Debug "mo:base/Debug";
let array = [var 0, 1, 2, 3];
VarArray.forEach<Nat>(array, func(x) {
Debug.print(debug_show x)
})
Runtime: O(size)
Space: O(size)
*Runtime and space assumes that f
runs in O(1) time and space.
public func map<T, R>(array : [var T], f : T -> R) : [var R]
Creates a new mutable array by applying f
to each element in array
. f
"maps"
each element it is applied to of type X
to an element of type Y
.
Retains original ordering of elements.
motoko include=import
let array = [var 0, 1, 2, 3];
VarArray.map<Nat, Nat>(array, func x = x * 3)
Runtime: O(size)
Space: O(size)
*Runtime and space assumes that f
runs in O(1) time and space.
public func mapInPlace<T>(array : [var T], f : T -> T)
Applies f
to each element of array
in place,
retaining the original ordering of elements.
motoko include=import
let array = [var 0, 1, 2, 3];
VarArray.mapInPlace<Nat>(array, func x = x * 3)
assert array == [0, 2, 4, 6];
Runtime: O(size)
Space: O(size)
*Runtime and space assumes that f
runs in O(1) time and space.
public func filter<T>(array : [var T], f : T -> Bool) : [var T]
Creates a new mutable array by applying predicate
to every element
in array
, retaining the elements for which predicate
returns true.
motoko include=import
let array = [var 4, 2, 6, 1, 5];
let evenElements = VarArray.filter<Nat>(array, func x = x % 2 == 0);
Runtime: O(size)
Space: O(size)
*Runtime and space assumes that predicate
runs in O(1) time and space.
public func filterMap<T, R>(array : [var T], f : T -> ?R) : [var R]
Creates a new array by applying f
to each element in array
,
and keeping all non-null elements. The ordering is retained.
motoko include=import
import {toText} "mo:base/Nat";
let array = [var 4, 2, 0, 1];
let newArray =
VarArray.filterMap<Nat, Text>( // mapping from Nat to Text values
array,
func x = if (x == 0) { null } else { ?toText(100 / x) } // can't divide by 0, so return null
);
Runtime: O(size)
Space: O(size)
*Runtime and space assumes that f
runs in O(1) time and space.
public func mapResult<T, R, E>(array : [var T], f : T -> Result.Result<R, E>) : Result.Result<[var R], E>
Creates a new array by applying f
to each element in array
.
If any invocation of f
produces an #err
, returns an #err
. Otherwise
returns an #ok
containing the new array.
motoko include=import
let array = [var 4, 3, 2, 1, 0];
// divide 100 by every element in the array
VarArray.mapResult<Nat, Nat, Text>(array, func x {
if (x > 0) {
#ok(100 / x)
} else {
#err "Cannot divide by zero"
}
})
Runtime: O(size)
Space: O(size)
*Runtime and space assumes that f
runs in O(1) time and space.
public func mapEntries<T, R>(array : [var T], f : (T, Nat) -> R) : [var R]
Creates a new array by applying f
to each element in array
and its index.
Retains original ordering of elements.
motoko include=import
let array = [10, 10, 10, 10];
Array.mapEntries<Nat, Nat>(array, func (x, i) = i * x)
Runtime: O(size)
Space: O(size)
*Runtime and space assumes that f
runs in O(1) time and space.
public func flatMap<T, R>(array : [var T], k : T -> Iter.Iter<R>) : [var R]
Creates a new array by applying k
to each element in array
,
and concatenating the resulting arrays in order.
motoko include=import
import Nat "mo:base/Nat";
let array = [var 1, 2, 3, 4];
VarArray.flatMap<Nat, Int>(array, func x = [x, -x])
Runtime: O(size)
Space: O(size)
*Runtime and space assumes that k
runs in O(1) time and space.
public func foldLeft<T, A>(
array : [var T],
base : A,
combine : (A, T) -> A
) : A
Collapses the elements in array
into a single value by starting with base
and progessively combining elements into base
with combine
. Iteration runs
left to right.
motoko include=import
import {add} "mo:base/Nat";
let array = [var 4, 2, 0, 1];
let sum =
VarArray.foldLeft<Nat, Nat>(
array,
0, // start the sum at 0
func(sumSoFar, x) = sumSoFar + x // this entire function can be replaced with `add`!
);
Runtime: O(size)
Space: O(1)
*Runtime and space assumes that combine
runs in O(1) time and space.
public func foldRight<T, A>(
array : [var T],
base : A,
combine : (T, A) -> A
) : A
Collapses the elements in array
into a single value by starting with base
and progessively combining elements into base
with combine
. Iteration runs
right to left.
motoko include=import
import {toText} "mo:base/Nat";
let array = [1, 9, 4, 8];
let bookTitle = VarArray.foldRight<Nat, Text>(array, "", func(x, acc) = toText(x) # acc);
Runtime: O(size)
Space: O(1)
*Runtime and space assumes that combine
runs in O(1) time and space.
public func join<T>(arrays : Iter.Iter<[var T]>) : [var T]
Combines an iterator of mutable arrays into a single mutable array. Retains the original ordering of the elements.
Consider using VarArray.flatten()
where possible for better performance.
motoko include=import
let arrays = [[var 0, 1, 2], [var 2, 3], [var], [var 4]];
VarArray.join<Nat>(VarArray.fromIter(arrays)) // => [var 0, 1, 2, 2, 3, 4]
Runtime: O(number of elements in array)
Space: O(number of elements in array)
public func flatten<T>(arrays : [var [var T]]) : [var T]
Combines a mutable array of mutable arrays into a single mutable array. Retains the original ordering of the elements.
This has better performance compared to VarArray.flatten()
.
motoko include=import
let arrays = [var [var 0, 1, 2], [var 2, 3], [var], [var 4]];
VarArray.flatten<Nat>(arrays) // => [var 0, 1, 2, 2, 3, 4]
Runtime: O(number of elements in array)
Space: O(number of elements in array)
public func singleton<T>(element : T) : [var T]
Create an array containing a single value.
motoko include=import
let array = VarArray.singleton(2);
assert array == [var 2];
Runtime: O(1)
Space: O(1)
public func size<T>(array : [var T]) : Nat
Returns the size of a mutable array. Equivalent to array.size()
.
public func isEmpty<T>(array : [var T]) : Bool
Returns whether a mutable array is empty, i.e. contains zero elements.
public func fromIter<T>(iter : Iter.Iter<T>) : [var T]
Converts an iterator to a mutable array.
public func keys<T>(array : [var T]) : Iter.Iter<Nat>
Returns an iterator (Iter
) over the indices of array
.
An iterator provides a single method next()
, which returns
indices in order, or null
when out of index to iterate over.
NOTE: You can also use array.keys()
instead of this function. See example
below.
motoko include=import
let array = [var 10, 11, 12];
var sum = 0;
for (element in array.keys()) {
sum += element;
};
sum
Runtime: O(1)
Space: O(1)
public func values<T>(array : [var T]) : Iter.Iter<T>
Iterator provides a single method next()
, which returns
elements in order, or null
when out of elements to iterate over.
Note: You can also use array.values()
instead of this function. See example
below.
motoko include=import
let array = [var 10, 11, 12];
var sum = 0;
for (element in array.values()) {
sum += element;
};
sum
Runtime: O(1)
Space: O(1)
public func enumerate<T>(array : [var T]) : Iter.Iter<(Nat, T)>
Iterator provides a single method next()
, which returns
pairs of (index, element) in order, or null
when out of elements to iterate over.
motoko include=import
let array = [var 10, 11, 12];
var sum = 0;
for ((index, element) in Array.enumerate(array)) {
sum += element;
};
sum // => 33
Runtime: O(1)
Space: O(1)
public func all<T>(array : [var T], predicate : T -> Bool) : Bool
Returns true if all elements in array
satisfy the predicate function.
motoko include=import
let array = [var 1, 2, 3, 4];
VarArray.all<Nat>(array, func x = x > 0) // => true
Runtime: O(size)
Space: O(1)
*Runtime and space assumes that predicate
runs in O(1) time and space.
public func any<T>(array : [var T], predicate : T -> Bool) : Bool
Returns true if any element in array
satisfies the predicate function.
motoko include=import
let array = [var 1, 2, 3, 4];
VarArray.any<Nat>(array, func x = x > 3) // => true
Runtime: O(size)
Space: O(1)
*Runtime and space assumes that predicate
runs in O(1) time and space.
public func subArray<T>(
array : [var T],
start : Nat,
length : Nat
) : [var T]
Returns a new sub-array from the given array provided the start index and length of elements in the sub-array.
Limitations: Traps if the start index + length is greater than the size of the array
motoko include=import
let array = [1, 2, 3, 4, 5];
let subArray = VarArray.subArray<Nat>(array, 2, 3);
Runtime: O(length)
Space: O(length)
public func indexOf<T>(
element : T,
array : [var T],
equal : (T, T) -> Bool
) : ?Nat
Returns the index of the first element
in the array
.
motoko include=import
import Char "mo:base/Char";
let array = [var 'c', 'o', 'f', 'f', 'e', 'e'];
assert VarArray.indexOf<Char>('c', array, Char.equal) == ?0;
assert VarArray.indexOf<Char>('f', array, Char.equal) == ?2;
assert VarArray.indexOf<Char>('g', array, Char.equal) == null;
Runtime: O(array.size())
Space: O(1)
public func nextIndexOf<T>(
element : T,
array : [var T],
fromInclusive : Nat,
equal : (T, T) -> Bool
) : ?Nat
Returns the index of the next occurence of element
in the array
starting from the from
index (inclusive).
motoko include=import
import Char "mo:base/Char";
let array = [var 'c', 'o', 'f', 'f', 'e', 'e'];
assert VarArray.nextIndexOf<Char>('c', array, 0, Char.equal) == ?0;
assert VarArray.nextIndexOf<Char>('f', array, 0, Char.equal) == ?2;
assert VarArray.nextIndexOf<Char>('f', array, 2, Char.equal) == ?2;
assert VarArray.nextIndexOf<Char>('f', array, 3, Char.equal) == ?3;
assert VarArray.nextIndexOf<Char>('f', array, 4, Char.equal) == null;
Runtime: O(array.size())
Space: O(1)
public func lastIndexOf<T>(
element : T,
array : [var T],
equal : (T, T) -> Bool
) : ?Nat
Returns the index of the last element
in the array
.
motoko include=import
import Char "mo:base/Char";
let array = [var 'c', 'o', 'f', 'f', 'e', 'e'];
assert VarArray.lastIndexOf<Char>('c', array, Char.equal) == ?0;
assert VarArray.lastIndexOf<Char>('f', array, Char.equal) == ?3;
assert VarArray.lastIndexOf<Char>('e', array, Char.equal) == ?5;
assert VarArray.lastIndexOf<Char>('g', array, Char.equal) == null;
Runtime: O(array.size())
Space: O(1)
public func prevIndexOf<T>(
element : T,
array : [var T],
fromExclusive : Nat,
equal : (T, T) -> Bool
) : ?Nat
Returns the index of the previous occurence of element
in the array
starting from the from
index (exclusive).
motoko include=import
import Char "mo:base/Char";
let array = [var 'c', 'o', 'f', 'f', 'e', 'e'];
assert VarArray.prevIndexOf<Char>('c', array, array.size(), Char.equal) == ?0;
assert VarArray.prevIndexOf<Char>('e', array, array.size(), Char.equal) == ?5;
assert VarArray.prevIndexOf<Char>('e', array, 5, Char.equal) == ?4;
assert VarArray.prevIndexOf<Char>('e', array, 4, Char.equal) == null;
Runtime: O(array.size()); Space: O(1);
public func range<T>(
array : [var T],
fromInclusive : Int,
toExclusive : Int
) : Iter.Iter<T>
Returns an iterator over a slice of the given array.
motoko include=import
let array = [var 1, 2, 3, 4, 5];
let s = VarArray.range<Nat>(array, 3, array.size());
assert s.next() == ?4;
assert s.next() == ?5;
assert s.next() == null;
let s = Array.range<Nat>(array, 0, 0);
assert s.next() == null;
Runtime: O(1)
Space: O(1)
public func toText<T>(array : [var T], f : T -> Text) : Text
Converts the mutable array to its textual representation using f
to convert each element to Text
.
motoko include=import
import Nat "mo:base/Nat";
let array = [var 1, 2, 3];
VarArray.toText<Nat>(array, Nat.toText) // => "[var 1, 2, 3]"
Runtime: O(size)
Space: O(size)
*Runtime and space assumes that f
runs in O(1) time and space.
public func compare<T>(
array1 : [var T],
array2 : [var T],
compare : (T, T) -> Order.Order
) : Order.Order
Compares two mutable arrays using the provided comparison function for elements.
Returns #less, #equal, or #greater if array1
is less than, equal to,
or greater than array2
respectively.
If arrays have different sizes but all elements up to the shorter length are equal, the shorter array is considered #less than the longer array.
motoko include=import
import Nat "mo:base/Nat";
let array1 = [var 1, 2, 3];
let array2 = [var 1, 2, 4];
VarArray.compare<Nat>(array1, array2, Nat.compare) // => #less
let array3 = [var 1, 2];
let array4 = [var 1, 2, 3];
VarArray.compare<Nat>(array3, array4, Nat.compare) // => #less (shorter array)
Runtime: O(min(size1, size2))
Space: O(1)
*Runtime and space assumes that compare
runs in O(1) time and space.