The iiris/array
module includes functions for working with Arrays. It is
designed to be imported with a wildcard, e.g.
import * as A from 'iiris/array'
- Basic array operations
- Building arrays
- Grouping arrays by key
- Reducing arrays
- Searching arrays by value
- Searching arrays with a predicate
- Slicing arrays
- Sorting arrays
- Transforming arrays
- Zipping arrays
<T>(value: T) => (array: T[]) => T[]
Append a new element to the end of an array.
A.append(4, [1, 2, 3])
// => [1, 2, 3, 4]
<T>(array: T[]) => (other: T[]) => T[]
Concatenate two arrays together.
A.concat([1, 2, 3], [4, 5, 6])
// => [1, 2, 3, 4, 5, 6]
<T>(fn: (value: T) => void) => (array: T[]) => T[]
Apply fn
to each element of the array
and return the array
.
A.forEach(console.log, ['h', 'i', '!'])
h
i
!
// => ['h', 'i', '!']
See also: forEachWithIndex
<T>(fn: (index: number, value: T) => void) => (array: T[]) => T[]
Like forEach, but fn
also receives the element index as the first argument.
A.forEachWithIndex(console.log, ['h', 'i', '!'])
0 h
1 i
2 !
// => ['h', 'i', '!']
See also: forEach
(index: number) => <T>(array: T[]) => T | undefined
Return the element at index
from array
or undefined
.
A.get(0, [1, 2, 3])
// => 1
A.get(0, [])
// => undefined
See also: getOr
<T>(defaultValue: T) => (index: number) => (array: T[]) => T
Like get, but if index
is not within the array bounds,
defaultValue
is returned instead.
A.getOr(999, 0, [1, 2, 3])
// => 1
A.getOr(999, 0, [])
// => 999
A.getOr(999, 0, [undefined])
// => 999
See also: get
<T>(array: T[]) => T | undefined
Return the first element of the array
or undefined
.
A.head([1, 2, 3])
// => 1
A.head([])
// => undefined
<T>(array: T[]) => T[]
Return all elements of the array
except the last.
A.init([1, 2, 3])
// => [1, 2]
A.init([])
// => []
<T>(array: T[]) => boolean
Check if array
is empty.
A.isEmpty([1, 2, 3])
// => false
A.isEmpty([])
// => true
See also: length
<T>(array: T[]) => T | undefined
Return the last element of the array
or undefined
.
A.last([1, 2, 3])
// => 3
A.last([])
// => undefined
<T>(array: T[]) => number
Return the length of an array
.
A.length([1, 2, 3])
// => 3
A.length([])
// => 0
See also: isEmpty
(index: number) => <T>(fn: (value: T) => T) => (array: T[]) => T[]
Returns a copy of array
where the element at index
has been replaced by
applying fn
to its current value. If index
is not within array
bounds,
the array
is returned unchanged.
A.modify(0, (n) => n + 1, [1, 2, 3])
// => [2, 2, 3]
A.modify(-1, (n) => n + 1, [1, 2, 3])
// => [1, 2, 4]
A.modify(0, () => undefined, [1, 2, 3])
// => [2, 3]
A.modify(999, (n) => n + 1, [1, 2, 3])
// => [1, 2, 3]
<T>(value: T) => (array: T[]) => T[]
Prepend a new element to the beginning of an array.
A.prepend(0, [1, 2, 3])
// => [0, 1, 2, 3]
(index: number) => <T>(array: T[]) => T[]
Return a copy of array
without the element at index
. If index
is not
within the array
bounds, the array
is returned unchanged.
A.remove(0, [1, 2, 3])
// => [2, 3]
A.remove(-1, [1, 2, 3])
// => [1, 2]
A.remove(999, [1, 2, 3])
// => [1, 2, 3]
(index: number) => <T>(value: T) => (array: T[]) => T[]
Returns a copy of array
where the element at index
has been replaced with
value
. If index
is not within the array
bounds, the array
is returned
unchanged.
A.set(0, 999, [1, 2, 3])
// => [999, 2, 3]
A.set(-1, 999, [1, 2, 3])
// => [1, 2, 999]
A.set(999, 999, [1, 2, 3])
// => [1, 2, 3]
<T>(array: T[]) => T[]
Return all elements of the array
except the first.
A.tail([1, 2, 3])
// => [2, 3]
A.tail([])
// => []
<T>() => T[]
Create an empty array.
A.empty()
// => []
<T>(iterable: Iterable<T>) => T[]
Convert an iterable
into an array.
A.from
is like Array.from
but without support for mapping the values.
A.from(new Set([1, 2, 3))
// => [1, 2, 3]
(start: number) => (end: number) => number[]
Create an array of numbers between start
(inclusive) and end
(exclusive).
A.range(0, 10)
// => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
A.range(0, 0)
// => []
<T>(value: T) => (n: number) => T[]
Repeat the given value
n
times.
A.repeat('a', 5)
// => ['a', 'a', 'a', 'a', 'a']
<T>(values: T) => [T]
Create a singleton array containing value
A.of(1)
// => [1]
A.of(1, 2, 3)
// => [1, 2, 3]
<T>(fn: (index: number) => T) => (n: number) => T[]
Create an array of length n
by applying fn
to the index of each element.
A.times((n) => n * 10, 3)
// => [0, 10, 20]
<T, K extends string>(keyFn: (value: T) => K) => (array: T[]) => Record<K, number>
Apply keyFn
to each element in the array
and return an object of counts by key.
const users = [{ name: 'Alice' }, { name: 'Bob' }, { name: 'Alice' }]
A.countBy((u) => u.name, users)
// => { Alice: 2, Bob: 1 }
See also: groupBy
<T, K extends string>(keyFn: (value: T) => K) => (array: T[]) => Record<K, T[]>
Partition the array
into an object of arrays according to keyFn
.
const users = [{ name: 'Alice' }, { name: 'Bob' }, { name: 'Alice' }]
A.groupBy((u) => u.name, users)
// => { Alice: [{ name: 'Alice' }, { name: 'Alice' }], Bob: [{ name: 'Bob' }] }
See also: indexBy, countBy, groupMap, groupMapReduce
<T, U>(mapFn: (value: T) => U) => <K extends string>(keyFn: (value: T) => K) => (array: T[]) => Record<K, U[]>
Like groupBy, but also apply mapFn
to each element before adding it
to the corresponding array.
const users = [
{ name: 'Alice', age: 10 },
{ name: 'Bob', age: 20 },
{ name: 'Alice', age: 30 },
]
const agesByName = A.groupMap(
(u) => u.age,
(u) => u.name,
users
)
// => { Alice: [10, 30], Bob: [20] }
See also: groupBy, groupMapReduce
<U>(reducer: (accumulator: U, value: U) => U) => <T>(mapFn: (value: T) => U) => <K extends string>(keyFn: (value: T) => K) => (array: T[]) => Record<K, U>
Like groupMap, but instead of returning an object of arrays, combine
elements mapping to the same key with reducer
.
const users = [
{ name: 'Alice', age: 10 },
{ name: 'Bob', age: 20 },
{ name: 'Alice', age: 30 },
]
const sumOfAgesByName = A.groupMapReduce(
(sum, n) => sum + n,
(u) => u.age,
(u) => u.name,
users
) // => { Alice: 40, Bob: 20 }
<T, K extends string>(keyFn: (value: T) => K) => (array: T[]) => Record<K, T>
Apply keyFn
to each element in the array
and return an object of elements
indexed by each key.
If multiple elements map to the same key, the last one is selected.
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 1, name: 'Carol' },
]
A.indexBy((u) => u.id, users)
// => { '1': { id: 1, name: 'Carol' }, '2': { id: 2, name: 'Bob' } }
See also: groupBy
<T extends Ordered>(array: T[]) => T | undefined
Return the smallest element of array
or undefined
.
A.minimum([1, 2, 3])
// => 1
A.minimum([])
// => undefined
<T, U extends Ordered>(fn: (value: T) => U) => (array: T[]) => T | undefined
Like minimum, but fn
is applied to each value before determining
their ordering.
const users = [
{ name: 'Alice', age: 10 },
{ name: 'Bob', age: 20 },
{ name: 'Carol', age: 30 },
]
A.minimumBy((u) => u.age, users)
// => { name: 'Alice', age: 10 }
<T, R>(reducer: (accumulator: R, value: T) => R) => (initial: R) => (array: T[]) => R
Left-associative fold.
Combine the elements of an array
in to a single value by calling reducer
with the accumulated value so far and the current element. The first call to
reducer
receives initial
as the accumulator.
If the array is empty, initial
is returned.
A.reduce((sum, n) => sum + n, 1, [2, 3, 4]) // equal to ((1 + 2) + 3) + 4
// => 10
See also: reduceRight
<T, R>(reducer: (value: T, accumulator: R) => R) => (initial: R) => (array: T[]) => R
Right-associative fold.
Combine the elements of an array
in to a single value by calling reducer
with the current element and the accumulated value so far. The first call to
reducer
receives initial
as the accumulator.
If the array is empty, initial
is returned.
A.reduceRight((n, sum) => n + sum, 4, [1, 2, 3]) // equal to 1 + (2 + (3 + 4))
// => 10
See also: reduce
(numbers: number[]) => number
Sum an array
of numbers together. Returns 0
if the array is empty.
Uses the {@link https://en.wikipedia.org/wiki/Kahan_summation_algorithm Kahan summation algorithm} for minimizing numerical error.
const numbers = A.repeat(0.1, 10)
// => [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]
A.sum(numbers)
// => 1
numbers.reduce((sum, n) => sum + n, 0)
// => 0.9999999999999999
See also: sumBy
<T>(fn: (value: T) => number) => (array: T[]) => number
Like sum, but each element of the array
is converted to a number by
applying fn
.
A.sumBy((u) => u.age, [
{ name: 'Alice', age: 10 },
{ name: 'Bob', age: 20 },
])
// => 30
See also: sum
<T>(value: T) => (array: T[]) => boolean
Check if the array
includes the specified value
, using equals for
determining equality.
A.includes(1, [1, 2, 3])
// => true
A.includes(0, [1, 2, 3])
// => false
<T>(value: T) => (array: T[]) => number
Return the index of the first element equaling value
, using equals
for determining equality. Returns -1
if no match can be found.
A.indexOf('b', ['a', 'b', 'c', 'a', 'b', 'c'])
// => 1
A.indexOf('x', ['a', 'b', 'c', 'a', 'b', 'c'])
// => -1
See also: lastIndexOf, includes
<T>(value: T) => (array: T[]) => number
Return the index of the last element equaling value
, using equals
for determining equality. Returns -1
if no match can be found.
A.lastIndexOf('b', ['a', 'b', 'c', 'a', 'b', 'c'])
// => 4
A.lastIndexOf('x', ['a', 'b', 'c', 'a', 'b', 'c'])
// => -1
<T>(predicate: (value: T) => boolean) => (array: T[]) => number
Count the number of elements in the array
the satisfy the predicate
.
A.count((n) => n > 1, [1, 2, 3])
// => 2
See also: filter
<T>(predicate: (value: T) => boolean) => (array: T[]) => boolean
Check if every element in the array
satisfies the predicate
.
A.every((n) => n < 10, [1, 2, 3])
// => true
A.every((n) => n < 3, [1, 2, 3])
// => false
<T>(predicate: (value: T) => boolean) => (array: T[]) => T[]
<T, U>(guard: (value: T) => value is U) => (array: T[]) => U[]
Return the elements of the array
that satisfy the predicate
.
A.filter((n) => n > 1, [1, 2, 3])
// => [2, 3]
See also: filterWithIndex, count, partition
<T>(predicate: (index: number, value: T) => boolean) => (array: T[]) => T[]
Like filter, but predicate
also receives the element index as the
first argument.
A.filterWithIndex((i, n) => i + n === 3, [1, 2, 3])
// => [2]
See also: filter
<T>(predicate: (value: T) => boolean) => (array: T[]) => T | undefined
<T, U>(guard: (value: T) => value is U) => (array: T[]) => U | undefined
Find the first element in the array
that satisfies the predicate
.
Returns undefined
if none of the elements match.
A.find((c) => c !== 'a', ['a', 'b', 'c'])
// => 'b'
A.find((c) => c === 'x', ['a', 'b', 'c'])
// => undefined
<T>(predicate: (value: T) => boolean) => (array: T[]) => number
Find the index of the first element in the array
that satisfies the predicate
.
Returns -1
if none of the elements satisfy the predicate.
A.findIndex((c) => c !== 'a', ['a', 'b', 'c'])
// => 1
A.findIndex((c) => c === 'x', ['a', 'b', 'c'])
// => -1
See also: findLastIndex, find
<T>(predicate: (value: T) => boolean) => (array: T[]) => T | undefined
<T, U>(guard: (value: T) => value is U) => (array: T[]) => U | undefined
Find the last element in the array
that satisfies the predicate
.
Returns undefined
if none of the elements match.
A.findLast((c) => c !== 'a', ['a', 'b', 'c'])
// => 'c'
A.findLast((c) => c === 'x', ['a', 'b', 'c'])
// => undefined
See also: find, findLastIndex
<T>(predicate: (value: T) => boolean) => (array: T[]) => number
Find the index of the last element in the array
that satisfies the predicate
.
Returns -1
if none of the elements match.
A.findLastIndex((c) => c !== 'a', ['a', 'b', 'c'])
// => 2
A.findLastIndex((c) => c === 'x', ['a', 'b', 'c'])
// => -1
<T>(predicate: (value: T) => boolean) => (array: T[]) => boolean
Check if none of the elements in the array
satisfy the predicate
.
A.none((n) => n > 5, [1, 2, 3])
// => true
A.none((n) => n > 5, [1, 2, 3])
// => false
<T>(predicate: (value: T) => boolean) => (array: T[]) => [T[], T[]]
<T, U>(guard: (value: T) => value is U) => (array: T[]) => [U[], Array<Exclude<T, U>>]
Partition the array
into two arrays, the first containing the elements that
satisfy the predicate
and the second containing the elements that do not.
const [evens, odds] = A.partition((n) => n % 2 === 0, [1, 2, 3])
// => [[2], [1, 3]]
See also: filter
<T>(predicate: (value: T) => boolean) => (array: T[]) => boolean
Check if some elements in the array
satisfies the predicate
.
A.some((n) => n > 2, [1, 2, 3])
// true
A.some((n) => n > 5, [1, 2, 3])
// false
(n: number) => <T>(array: T[]) => T[]
Drop the first n
elements of an array
.
A.drop(1, [1, 2, 3])
// => [2, 3]
A.drop(2, [1, 2, 3])
// => [3]
(n: number) => <T>(array: T[]) => T[]
Drop the last n
elements of an array
.
A.dropLast(1, [1, 2, 3])
// => [1, 2]
A.dropLast(2, [1, 2, 3])
// => [1]
<T>(predicate: (value: T) => boolean) => (array: T[]) => T[]
Drop elements from the end of an array
while predicate
is satisfied.
A.dropLastWhile((n) => n > 1, [1, 2, 3])
// => [1]
See also: dropWhile, takeLastWhile
<T>(predicate: (value: T) => boolean) => (array: T[]) => T[]
Drop elements from the beginning of an array
while predicate
is satisfied.
A.dropWhile((n) => n === 1, [1, 2, 3])
// => [2, 3]
See also: dropLastWhile, takeWhile
(start: number) => (end: number) => <T>(array: T[]) => T[]
Create a copy of array
containing the elements from start
(inclusive) to
end
(exclusive).
A.slice(0, 2, [1, 2, 3])
// => [1, 2]
A.slice(1, 2, [1, 2, 3])
// => [2]
(n: number) => <T>(array: T[]) => T[]
Take the first n
elements of an array
.
A.take(2, [1, 2, 3])
// => [1, 2]
<T>(n: number) => (array: T[]) => T[]
Take the last n
elements of an array
.
A.takeLast(2, [1, 2, 3])
// => [2, 3]
<T>(predicate: (value: T) => boolean) => (array: T[]) => T[]
Take elements from the end of an array
while predicate
is satisfied.
A.takeLastWhile((n) => n >= 2, [1, 2, 3])
// => [2, 3]
See also: dropLastWhile, takeWhile
<T>(predicate: (value: T) => boolean) => (array: T[]) => T[]
Take elements from the beginning of an array
while predicate
is satisfied.
A.takeWhile((n) => n <= 2, [1, 2, 3])
// => [1, 2]
See also: dropWhile, takeLastWhile
<T>(comparator: (first: T, second: T) => number) => (array: T[]) => T[]
Sort an array
according to the comparator function.
A.sort((a, b) => a - b, [3, 2, 1])
// => [1, 2, 3]
See also: sortBy, sortWith, ascend, descend
<T, U extends Ordered>(fn: (value: T) => U) => (array: T[]) => T[]
Sort an array
into ascending order by mapping each element of the array with fn
.
const users = [
{ name: 'Bob', age: 10 },
{ name: 'Alice', age: 20 },
]
A.sortBy((u) => u.name, users)
// => [{ name: 'Alice', age: 20 }, { name: 'Bob', age: 10 }]
A.sortBy((u) => u.age, users)
// => [{ name: 'Bob', age: 10 }, { name: 'Alice', age: 20 }]
<T>(comparators: Array<(first: T, second: T) => number>) => (array: T[]) => T[]
Sort an array
according to an array of comparator functions.
The comparators are tried in order until an ordering has been found.
const users = [
{ name: 'Alice', age: 10 },
{ name: 'Bob', age: 20 },
{ name: 'Alice', age: 20 },
]
A.sortWith([F.descend((u) => u.age), F.ascend((u) => u.name)], users)
// => [{ name: 'Alice', age: 20 }, { name: 'Bob', age: 20 }, { name: 'Alice', age: 10 }]
See also: sort, sortBy, ascend, descend
<T, U>(fn: (value: T) => U[]) => (array: T[]) => U[]
Return an array containing the results of applying fn
to each element in
the original array
and then flattening the result by one level.
A.flatMap((n) => [n, n], [1, 2, 3])
// => [1, 1, 2, 2, 3, 3]
<D extends number>(depth: D) => <T extends unknown[]>(array: T) => Array<FlatArray<T, D>>
Flatten a nested array
by n
levels.
A.flatten(1, [1, [2, [3]]])
// => [1, 2, [3]]
A.flatten(2, [1, [2, [3]]])
// => [1, 2, 3]
See also: flatMap
<T>(separator: T) => (array: T[]) => T[]
Return a copy of array
with separator
inserted between each element.
A.intersperse(',', ['a', 'b', 'c'])
// => ['a', ',', 'b', ',', 'c']
A.intersperse(',', [])
// => []
See also: join
(separator: string) => <T>(array: T[]) => string
Convert the array
to a string, inserting the separator
between each element.
A.join(', ', [1, 2, 3])
// => '1, 2, 3'
See also: split, intersperse
<T, U>(fn: (value: T) => U) => (array: T[]) => U[]
Return an array containing the results of applying fn
to each element in
the original array
.
A.map((n) => n + 1, [1, 2, 3])
// => [2, 3, 4]
See also: mapWithIndex, mapMaybe, flatMap
<T, U>(fn: (value: T) => U | undefined) => (array: T[]) => U[]
Return an array containing the results of applying fn
to each element in
the original array
, discarding any undefined
values.
const users = [
{ name: 'Alice', age: 10 },
{ name: 'Bob', age: undefined },
{ name: 'Carol', age: 20 },
]
A.mapMaybe((u) => u.age, users)
// => [10, 20]
See also: map
<T, U>(fn: (index: number, value: T) => U) => (array: T[]) => U[]
Like map, but fn
also receives the element index as the first argument.
A.mapWithIndex((i, c) => `${i}-${c}`, ['a', 'b', 'c'])
// => ['0-a', '1-b', '2-c']
See also: map
<T>(array: T[]) => T[]
Reverse an array
.
A.reverse([1, 2, 3])
// => [3, 2, 1]
<T>(first: T[]) => <U>(second: U[]) => Array<[T, U]>
Combine the corresponding elements of two arrays into an array of pairs.
If one of the arrays is longer than the other, the extra elements are ignored.
A.zip(['a', 'b', 'c'], [1, 2, 3])
// => [['a', 1], ['b', 2], ['c', 3]]
<K extends string>(keys: K[]) => <T>(values: T[]) => Record<K, T>
Combine an array of keys
and values
into an object.
If one of the arrays is longer than the other, its extra elements are ignored.
A.zipObject(['a', 'b', 'c'], [1, 2, 3])
// => { a: 1, b: 2, c: 3 }
See also: zip, fromEntries
<T, U, R>(fn: (value: T, other: U) => R) => (first: T[]) => (second: U[]) => R[]
Like zip, but the elements are combined with fn
instead of
constructing a pair.
A.zipWith((a, b) => a + b, [1, 2, 3], [4, 5, 6])
// => [5, 7, 9]
See also: zip