Array
Utililites for Array
functions.
Note about index syntax
Code like arr[0]
does not compile to JavaScript arr[0]
. Reason transforms the []
index syntax into a function: Array.get(arr, 0)
. By default, this uses the default standard library's Array.get
function, which may raise an exception if the index isn't found. If you open Belt
, it will use the Belt.Array.get
function which returns options instead of raising exceptions. See this for more information.
let length: array('a) => int;
return the size of the array
RE/* Returns 1 */
Belt.Array.length([|"test"|]);
let size: array('a) => int;
See Belt_Array.length
let get: (array('a), int) => option('a);
If i <= 0 <= length(arr)
returns Some(value)
where value
is the item at index i
.
If i
is out of range returns None
let getExn: (array('a), int) => 'a;
Raise an exception if i
is out of range.
Otherwise return the value at index i
in arr
.
let getUnsafe: (array('a), int) => 'a;
Unsafe
no bounds checking; this would cause type error if i
does not stay within range
let getUndefined: (array('a), int) => Js.undefined('a);
It does the samething in the runtime as Belt_Array.getUnsafe
it is type safe since the return type still track whether it is in range or not
let set: (array('a), int, 'a) => bool;
set(arr, n, x);
modifies arr
in place; it replaces the nth element of arr
with x
.
Returns false means not updated due to out of range.
let setExn: (array('a), int, 'a) => unit;
setExn(arr, i, x);
raise an exception if i
is out of range.
let setUnsafe: (array('a), int, 'a) => unit;
let shuffleInPlace: array('a) => unit;
shuffleInPlace(arr)
randomly re-orders the items in arr
let shuffle: array('a) => array('a);
Returns a fresh array with items in original array randomly shuffled.
let reverseInPlace: array('a) => unit;
reverseInPlace(arr)
reverses items in arr
in place.
RElet arr = [|10, 11, 12, 13, 14|];
let () = Belt.Array.reverseInPlace(arr);
arr == [|14, 13, 12, 11, 10|];
let reverse: array('a) => array('a);
reverse(arr)
returns a fresh array with items in arr in reverse order.
REBelt.Array.reverse([|10, 11, 12, 13, 14|]) == [|14, 13, 12, 11, 10|];
let makeUninitialized: int => array(Js.undefined('a));
makeUninitialized(n)
creates an array of length n
filled with the undefined value. You must specify the type of data that will eventually fill the array.
RElet arr: array(Js.undefined(string)) = Belt.Array.makeUninitialized(5);
Belt.Array.getExn(arr, 0) == Js.undefined;
let makeUninitializedUnsafe: int => array('a);
Unsafe
RElet arr = Belt.Array.makeUninitializedUnsafe(5);
let () = Js.log(Belt.Array.getExn(arr, 0)); /* undefined */
Belt.Array.setExn(arr, 0, "example");
let () = Js.log(Belt.Array.getExn(arr, 0) == "example");
let make: (int, 'a) => array('a);
make(n, e)
return an array of size n
filled with value e
.
Returns an empty array when n
is negative.
let range: (int, int) => array(int);
range(start, finish);
create an inclusive array.
REBelt.Array.range(0, 3) == [|0, 1, 2, 3|];
Belt.Array.range(3, 0) == [||];
Belt.Array.range(3, 3) == [|3|];
let rangeBy: (int, int, ~step: int) => array(int);
rangeBy(start, finish, ~step);
Returns empty array when step is 0 or negative. It also return an empty array when start > finish
.
REBelt.Array.rangeBy(0, 10, ~step=3) == [|0, 3, 6, 9|];
Belt.Array.rangeBy(0, 12, ~step=3) == [|0, 3, 6, 9, 12|];
Belt.Array.rangeBy(33, 0, ~step=1) == [||];
Belt.Array.rangeBy(33, 0, ~step=-1) == [||];
Belt.Array.rangeBy(3, 12, ~step=-1) == [||];
Belt.Array.rangeBy(3, 3, ~step=0) == [||];
Belt.Array.rangeBy(3, 3, ~step=1) == [|3|];
let makeByU: (int, [@bs] (int => 'a)) => array('a);
let makeBy: (int, int => 'a) => array('a);
makeBy(n, f);
Return an empty array when n is negative return an array of size n populated by f(i)
start from 0
to n - 1
.
REBelt.Array.makeBy(5, (i) => i) == [|0, 1, 2, 3, 4|];
Belt.Array.makeBy(5, (i) => i * i) == [|0, 1, 4, 9, 16|];
let makeByAndShuffleU: (int, [@bs] (int => 'a)) => array('a);
let makeByAndShuffle: (int, int => 'a) => array('a);
makeByAndShuffle(n, f);
Equivalent to shuffle(makeBy(n, f));
let zip: (array('a), array('b)) => array(('a, 'b));
zip(a, b);
Create an array of pairs from corresponding elements of a and b. Stop with the shorter array.
REBelt.Array.zip([|1, 2|], [|3, 4, 5|]) == [|(1, 3), (2, 4)|]
let zipByU: (array('a), array('b), [@bs] (('a, 'b) => 'c)) => array('c);
let zipBy: (array('a), array('b), ('a, 'b) => 'c) => array('c);
zipBy(xs, ys, f);
Create an array by applying f
to corresponding elements of xs
and ys
. Stops with shorter array.
Equivalent to map(zip(xs, ys), ((a, b)) => f(a, b));
REBelt.Array.zipBy([|1, 2, 3|], [|4, 5|], (a, b) => 2 * a + b) == [|6, 9|];
let unzip: array(('a, 'b)) => (array('a), array('b));
unzip(a);
takes an array of pairs and creates a pair of arrays. The first array contains all the first items of the pairs; the second array contains all the second items.
REBelt.Array.unzip([|(1, 2), (3, 4)|]) == ([|1, 3|], [|2, 4|]);
Belt.Array.unzip([|(1, 2), (3, 4), (5, 6), (7, 8)|]) == ([|1, 3, 5, 7|], [|2, 4, 6, 8|]);
let concat: (array('a), array('a)) => array('a);
concat(xs, ys);
Returns a fresh array containing the concatenation of the arrays v1
and v2
;so even if v1
or v2
is empty; it can not be shared
REBelt.Array.concat([|1, 2, 3|], [|4, 5|]) == [|1, 2, 3, 4, 5|];
Belt.Array.concat([||], [|"a", "b", "c"|]) == [|"a", "b", "c"|];
let concatMany: array(array('a)) => array('a);
concatMany(xss);
Returns a fresh array as the concatenation of xss
(an array of arrays)
REBelt.Array.concatMany([|[|1, 2, 3|], [|4, 5, 6|], [|7, 8|]|]) == [|1, 2, 3, 4, 5, 6, 7, 8|];
let slice: (array('a), ~offset: int, ~len: int) => array('a);
slice(xs, offset, len);
creates a new array with the len elements of xs
starting at offset
for offset
can be negative;and is evaluated as
length(xs) - offset(slice, xs) - 1(1);
means get the last element as a
singleton array slice(xs, ~-len, len);
will return a copy of the array if the
array does not have enough data; slice
extracts through the end of sequence.
if len
is negative; returns the empty array.
REBelt.Array.slice([|10, 11, 12, 13, 14, 15, 16|], ~offset=2, ~len=3) == [|12, 13, 14|];
Belt.Array.slice([|10, 11, 12, 13, 14, 15, 16|], ~offset=-4, ~len=3) == [|13, 14, 15|];
Belt.Array.slice([|10, 11, 12, 13, 14, 15, 16|], ~offset=4, ~len=9) == [|14, 15, 16|];
let sliceToEnd: (array('a), int) => array('a);
sliceToEnd(xs, offset);
creates a new array with the elements of xs
starting at offset
offset
can be negative; and is evaluated as length(xs) - offset(sliceToEnd, xs) - 1;
means get the last element as a singleton array
sliceToEnd(xs, 0);
will return a copy of the array
REBelt.Array.sliceToEnd([|10, 11, 12, 13, 14, 15, 16|], 2) == [|12, 13, 14, 15, 16|];
Belt.Array.sliceToEnd([|10, 11, 12, 13, 14, 15, 16|], -4) == [|13, 14, 15, 16|];
let copy: array('a) => array('a);
copy(a);
Returns a copy of a; that is; a fresh array containing the same elements as a.
let fill: (array('a), ~offset: int, ~len: int, 'a) => unit;
fill(arr, ~offset, ~len, x);
Modifies arr
in place, storing x
in elements number offset
to offset + len - 1
.
offset
can be negative; and is evaluated as length(arr - offset);
fill(arr, ~offset=-1, ~len=1);
means fill the last element, if the array does not have enough data; fill
will ignore it
RElet arr = Belt.Array.makeBy(5, (i) => i);
Belt.Array.fill(arr, ~offset=2, ~len=2, 9);
arr == [|0, 1, 9, 9, 4|];
Belt.Array.fill(arr, ~offset=7, ~len=2, 8);
arr == [|0, 1, 9, 9, 4|];
let blit:
(
~src: array('a),
~srcOffset: int,
~dst: array('a),
~dstOffset: int,
~len: int
) =>
unit;
blit(~src=v1, ~srcOffset=o1, ~dst=v2, ~dstOffset=o2, ~len);
copies len
elements from array v1
;starting at element number o1
;to array v2
, starting at element number o2
.
It works correctly even if v1
and v2
are the same array;and the source and destination chunks overlap.
offset
can be negative; -1
means len - 1
; if len + offset
is still negative;it will be set as 0
For each of the examples;presume that v1 == [|10, 11, 12, 13, 14, 15, 16, 17|];
and v2 == [|20, 21, 22, 23, 24, 25, 26, 27|];
. The result shown is the content of the destination array.
RElet v1 = [|10, 11, 12, 13, 14, 15, 16, 17|];
let v2 = [|20, 21, 22, 23, 24, 25, 26, 27|];
Belt.Array.blit(~src=v1, ~srcOffset=4, ~dst=v2, ~dstOffset=2, ~len=3);
v2 == [|20, 21, 14, 15, 16, 25, 26, 27|];
Belt.Array.blit(~src=v1, ~srcOffset=4, ~dst=v1, ~dstOffset=2, ~len=3);
v1 == [|10, 11, 14, 15, 16, 15, 16, 17|];
let blitUnsafe: (~src: array('a), ~srcOffset: int, ~dst: array('a), ~dstOffset: int, ~len: int) => unit;
Unsafe blit without bounds checking.
let forEachU: (array('a), [@bs] ('a => unit)) => unit;
let forEach: (array('a), 'a => unit) => unit;
forEach(xs, f);
Call f
on each element of xs
from the beginning to end. f
returns unit
;so no new array is created. Use forEach
when you are primarily concerned with repetitively creating side effects.
REBelt.Array.forEach([|"a", "b", "c"|], x => Js.log("Item: " ++ x));
/* prints:
Item: a
Item: b
Item: c
*/
let total = ref(0);
Belt.Array.forEach([|1, 2, 3, 4|], x => total := total^ + x);
total^ == 1 + 2 + 3 + 4;
let mapU: (array('a), [@bs] ('a => 'b)) => array('b);
let map: (array('a), 'a => 'b) => array('b);
map(xs, f);
Returns a new array by calling f
for each element of xs
from the beginning to end.
REBelt.Array.map([|1, 2|], (x) => x + 1) == [|3, 4|];
let getByU: (array('a), [@bs] ('a => bool)) => option('a);
let getBy: (array('a), 'a => bool) => option('a);
getBy(xs, p);
Returns Some(value)
for the first value in xs
that satisifies the predicate function p
; returns None
if no element satisifies the function.
REBelt.Array.getBy([|1, 4, 3, 2|], (x) => x mod 2 == 0) == Some(4);
Belt.Array.getBy([|15, 13, 11|], (x) => x mod 2 == 0) == None;
let getIndexByU: (array('a), [@bs] ('a => bool)) => option(int);
let getIndexBy: (array('a), 'a => bool) => option(int);
getIndexBy(xs, p);
returns Some(index)
for the first value in xs
that satisifies the predicate function p
;
returns None
if no element satisifies the function.
REBelt.Array.getIndexBy([|1, 4, 3, 2|], (x) => x mod 2 == 0) == Some(1);
Belt.Array.getIndexBy([|15, 13, 11|], (x) => x mod 2 == 0) == None;
let keepU: (array('a), [@bs] ('a => bool)) => array('a);
let keep: (array('a), 'a => bool) => array('a);
keep(xs, p);
Returns a new array that keep all elements satisfy p
.
REBelt.Array.keep([|1, 2, 3|], (x) => x mod 2 == 0) == [|2|];
let keepWithIndexU: (array('a), [@bs] (('a, int) => bool)) => array('a);
let keepWithIndex: (array('a), ('a, int) => bool) => array('a);
keepWithIndex(xs, p);
Returns a new array that keep all elements satisfy p
.
REBelt.Array.keepWithIndex([|1, 2, 3|], (_x, i) => i == 1) == [|2|];
let keepMapU: (array('a), [@bs] ('a => option('b))) => array('b);
let keepMap: (array('a), 'a => option('b)) => array('b);
keepMap(xs, p);
Returns a new array that keep all elements that return a non-None applied p
.
REBelt.Array.keepMap([|1, 2, 3|], x =>
if (x mod 2 == 0) {
Some(x);
} else {
None;
}
)
== [|2|];
let forEachWithIndexU: (array('a), [@bs] ((int, 'a) => unit)) => unit;
let forEachWithIndex: (array('a), (int, 'a) => unit) => unit;
forEachWithIndex(xs, f);
The same as Belt_Array.forEach
;
except that f
is supplied two arguments: the index starting from 0 and the element from xs
.
REBelt.Array.forEachWithIndex([|"a", "b", "c"|], (i, x) => Js.log("Item " ++ string_of_int(i) ++ " is " ++ x));
/* prints:
Item 0 is a
Item 1 is b
Item 2 is cc
*/
let total = ref(0);
Belt.Array.forEachWithIndex([|10, 11, 12, 13|], (i, x) => total := total^ + x + i);
total^ == 0 + 10 + 1 + 11 + 2 + 12 + 3 + 13;
let mapWithIndexU: (array('a), [@bs] ((int, 'a) => 'b)) => array('b);
let mapWithIndex: (array('a), (int, 'a) => 'b) => array('b);
mapWithIndex(xs, f);
mapWithIndex(xs, f)
applies f
to each element of xs
. Function f
takes two arguments: the index starting from 0 and the element from xs
.
REBelt.Array.mapWithIndex([|1, 2, 3|], (i, x) => i + x) == [|0 + 1, 1 + 2, 2 + 3|];
let partitionU: (array('a), [@bs] ('a => bool)) => (array('a), array('a));
let partition: (array('a), 'a => bool) => (array('a), array('a));
partition(f, a)
split array into tuple of two arrays based on predicate f
; first of tuple where predicate cause true, second where predicate cause false
REBelt.Array.partition([|1, 2, 3, 4, 5|], (x) => x mod 2 == 0) == ([|2, 4|], [|1, 2, 3|]);
Belt.Array.partition([|1, 2, 3, 4, 5|], (x) => x mod 2 != 0) == ([|1, 2, 3|], [|2, 4|]);
let reduceU: (array('b), 'a, [@bs] (('a, 'b) => 'a)) => 'a;
let reduce: (array('b), 'a, ('a, 'b) => 'a) => 'a;
reduce(xs, init, f);
Applies f
to each element of xs
from beginning to end. Function f
has two parameters: the item from the list and an “accumulator”; which starts with a value of init
. reduce
returns the final value of the accumulator.
REBelt.Array.reduce([|2, 3, 4|], 1, (+)) == 10;
Belt.Array.reduce([|"a", "b", "c", "d"|], "", (++)) == "abcd";
let reduceReverseU: (array('b), 'a, [@bs] (('a, 'b) => 'a)) => 'a;
let reduceReverse: (array('b), 'a, ('a, 'b) => 'a) => 'a;
reduceReverse(xs, init, f);
Works like Belt_Array.reduce
; except that function f
is applied to each item of xs
from the last back to the first.
REBelt.Array.reduceReverse([|"a", "b", "c", "d"|], "", (++)) == "dcba";
let reduceReverse2U: (array('a), array('b), 'c, [@bs] (('c, 'a, 'b) => 'c)) => 'c;
let reduceReverse2: (array('a), array('b), 'c, ('c, 'a, 'b) => 'c) => 'c;
reduceReverse2(xs, ys, init, f);
Reduces two arrays xs and ys;taking items starting at min(length(xs), length(ys))
down to and including zero.
REBelt.Array.reduceReverse2([|1, 2, 3|], [|1, 2|], 0, (acc, x, y) => acc + x + y) == 6;
let reduceWithIndexU: (array('a), 'b, [@bs] (('b, 'a, int) => 'b)) => 'b;
let reduceWithIndex: (array('a), 'b, ('b, 'a, int) => 'b) => 'b;
reduceWithIndex(xs, f);
Applies f
to each element of xs
from beginning to end. Function f
has three parameters: the item from the array and an “accumulator”, which starts with a value of init
and the index of each element. reduceWithIndex
returns the final value of the accumulator.
REBelt.Array.reduceWithIndex([|1, 2, 3, 4|], 0, (acc, x, i) => acc + x + i) == 16;
let someU: (array('a), [@bs] ('a => bool)) => bool;
let some: (array('a), 'a => bool) => bool;
some(xs, p);
Returns true if at least one of the elements in xs
satifies p
; where p
is a predicate: a function taking an element and returning a bool
.
REBelt.Array.some([|2, 3, 4|], (x) => x mod 2 == 1) == true;
Belt.Array.some([|(-1), (-3), (-5)|], (x) => x > 0) == false;
let everyU: (array('a), [@bs] ('a => bool)) => bool;
let every: (array('a), 'a => bool) => bool;
every(xs, p);
Returns true
if all elements satisfy p
; where p
is a predicate: a function taking an element and returning a bool
.
REBelt.Array.every([|1, 3, 5|], (x) => x mod 2 == 1) == true;
Belt.Array.every([|1, (-3), 5|], (x) => x > 0) == false;
let every2U: (array('a), array('b), [@bs] (('a, 'b) => bool)) => bool;
let every2: (array('a), array('b), ('a, 'b) => bool) => bool;
every2(xs, ys, p);
returns true if p(xi, yi);
is true for all pairs of elements up to the shorter length (i.e. min(length(xs), length(ys));
)
REBelt.Array.every2([|1, 2, 3|], [|0, 1|], (>)) == true;
Belt.Array.every2([||], [|1|], (x, y) => x > y) == true;
Belt.Array.every2([|2, 3|], [|1|], (x, y) => x > y) == true;
Belt.Array.every2([|0, 1|], [|5, 0|], (x, y) => x > y) == false;
let some2U: (array('a), array('b), [@bs] (('a, 'b) => bool)) => bool;
let some2: (array('a), array('b), ('a, 'b) => bool) => bool;
some2(xs, ys, p);
returns true if p(xi, yi);
is true for any pair of elements up to the shorter length (i.e. min(length(xs), length(ys));
)
REBelt.Array.some2([|0, 2|], [|1, 0, 3|], (>)) == true;
Belt.Array.some2([||], [|1|], (x, y) => x > y) == false;
Belt.Array.some2([|2, 3|], [|1, 4|], (x, y) => x > y) == true;
let cmpU: (array('a), array('a), [@bs] (('a, 'a) => int)) => int;
let cmp: (array('a), array('a), ('a, 'a) => int) => int;
cmp(xs, ys, f);
Compared by length if length(xs) != length(ys)
; returning -1 if length(xs) < length(ys)
or 1 if length(xs) > length(ys)
Otherwise compare one by one f(x, y);
. f
returns
a negative number if x
is “less than” y
zero if x
is “equal to” y
a positive number if x
is “greater than” y
The comparison returns the first non-zero result of f
;or zero if f
returns zero for all x
and y
.
REBelt.Array.cmp([|1, 3, 5|], [|1, 4, 2|], (a, b) => compare(a, b)) == (-1);
Belt.Array.cmp([|1, 3, 5|], [|1, 2, 3|], (a, b) => compare(a, b)) == 1;
Belt.Array.cmp([|1, 3, 5|], [|1, 3, 5|], (a, b) => compare(a, b)) == 0;
let eqU: (array('a), array('a), [@bs] (('a, 'a) => bool)) => bool;
let eq: (array('a), array('a), ('a, 'a) => bool) => bool;
eq(xs, ys);
return false if length is not the same
otherwise compare items one by one using f(xi, yi);
; and return true if all results are true;false otherwise
REBelt.Array.eq([|1, 2, 3|], [|(-1), (-2), (-3)|], (a, b) => abs(a) == abs(b)) == true;
let truncateToLengthUnsafe: (array('a), int) => unit;
Unsafe truncateToLengthUnsafe(xs, n);
sets length of array xs
to n
.
If n
is greater than the length of xs
; the extra elements are set to Js.Null_undefined.null
.
If n
is less than zero; raises a RangeError
.
RElet arr = [|"ant", "bee", "cat", "dog", "elk"|];
Belt.Array.truncateToLengthUnsafe(arr, 3);
arr == [|"ant", "bee", "cat"|];