A library that adds common array higher order function support beyond the built
in functions in js, e.g. map
, filter
, by extending the Array
prototype.
Inspired by swift and LINQ.
npm i ts-array-extensions
You can import
all the functions
import 'ts-array-extensions';
or individual ones as you need them
import 'ts-array-extensions/compactMap';
- any
- compact
- compactMap
- compactMapAsync
- cume
- distinct
- except
- first
- forEachAsync
- groupBy
- innerJoin
- interleave
- leftJoin
- mapAsync
- max
- min
- none
- outerJoin
- sortBy
- sum
- toRecord
- union
Returns true
if the array contains any elements.
[1, 2, 3].any();
// true
[].any();
// false
Returns elements of the array that are not null
or undefined
.
[1, null, 2].compact();
// [1, 2]
Maps elements and returns results that are not null
or undefined
.
[1, 2, 3].compactMap(v => {
if (v % 2 !== 0) return v;
});
// [1, 3]
Same as compactMap but works with promises. Will await async
callbacks.
await [1, 2, 3].compactMapAsync(async v => {
await /* something */
return v;
});
// [1, 2, 3]
Returns the a running total of all the elements in the array, optionally mapping them first with a callback
[1, 10, 100].cume();
// [1, 11, 111]
[1, 10, 100].cume(v => v * 10);
// [10, 110, 1110]
Returns elements of the array that are unique, using a comparer function if
supplied, or ===
if not.
[1, 1, 2, 2].distinct();
// [1, 2]
[
{ day: 1, month: 1, year: 1979 },
{ day: 1, month: 1, year: 1979 },
{ day: 2, month: 1, year: 1979 },
{ day: 2, month: 1, year: 1979 }
].distinct(
(a, b) => a.day === b.day && a.month === b.month && a.year === b.year
);
// [
// { day: 1, month: 1, year: 1979 },
// { day: 2, month: 1, year: 1979 }
// ]
Returns values from the first array, that aren't present in the second, using a
comparer function if supplied, or ===
if not.
[1, 2, 3].except([2, 3, 4]);
// [1]
[
{ day: 1, month: 1, year: 1979 },
{ day: 2, month: 1, year: 1979 }
].except(
[
{ day: 2, month: 1, year: 1979 },
{ day: 3, month: 1, year: 1979 }
],
(a, b) => a.day === b.day && a.month === b.month && a.year === b.year
);
// [
// { day: 1, month: 1, year: 1979 }
// ]
Returns the first element of the array or null
if empty.
['morning', 'afternoon'].first();
// 'morning'
Same as forEach but works with promises. Will await async
callbacks.
await [1, 2, 3].forEachAsync(async v => {
await /* something */
});
Returns an array of Group<K, V>
extracted from the array using a callback, and
an optional key comparer.
[
{ make: 'Ford', model: 'Fiesta' },
{ make: 'Ford', model: 'Focus' },
{ make: 'Vauxhall', model: 'Corsa' },
{ make: 'Vauxhall', model: 'Astra' }
].groupBy(k => k.make);
// [
// {
// key: 'Ford',
// values: [
// { make: 'Ford', model: 'Fiesta' },
// { make: 'Ford', model: 'Focus' }
// ]
// },
// {
// key: 'Vauxhall',
// values: [
// { make: 'Vauxhall', model: 'Corsa' },
// { make: 'Vauxhall', model: 'Astra' }
// ]
// }
// ]
Matches two array using a callback and returns the joined results.
const leftData = [
{ id: 1, name: 'Apples', groupId: 1 },
{ id: 2, name: 'Oranges', groupId: 1 },
{ id: 3, name: 'Cornflakes', groupId: 2 },
{ id: 4, name: 'Random', groupId: null }
];
const rightData = [
{ id: 1, name: 'Produce' },
{ id: 2, name: 'Grocery' },
{ id: 3, name: 'Confectionary' }
];
leftData.innerJoin(rightData, (l, r) => l.groupId === r.id);
// [
// {
// left: { id: 1, name: 'Apples', groupId: 1 },
// right: { id: 1, name: 'Produce' }
// },
// {
// left: { id: 2, name: 'Oranges', groupId: 1 },
// right: { id: 1, name: 'Produce' }
// },
// {
// left: { id: 3, name: 'Cornflakes', groupId: 2 },
// right: { id: 2, name: 'Grocery' }
// }
// ];
Adds new elements in between each element of an array.
['one', 'two', 'three'].interleave(() => 'and');
// ['one', 'and', 'two', 'and', 'three']
Matches two array using a callback and returns the joined results and unmatched results from the left array.
const leftData = [
{ id: 1, name: 'Apples', groupId: 1 },
{ id: 2, name: 'Oranges', groupId: 1 },
{ id: 3, name: 'Cornflakes', groupId: 2 },
{ id: 4, name: 'Random', groupId: null }
];
const rightData = [
{ id: 1, name: 'Produce' },
{ id: 2, name: 'Grocery' },
{ id: 3, name: 'Confectionary' }
];
leftData.leftJoin(rightData, (l, r) => l.groupId === r.id);
// [
// {
// left: { id: 1, name: 'Apples', groupId: 1 },
// right: { id: 1, name: 'Produce' }
// },
// {
// left: { id: 2, name: 'Oranges', groupId: 1 },
// right: { id: 1, name: 'Produce' }
// },
// {
// left: { id: 3, name: 'Cornflakes', groupId: 2 },
// right: { id: 2, name: 'Grocery' }
// },
// {
// left: { id: 4, name: 'Random', groupId: null },
// right: null
// }
// ];
Same as map but works with promises. Will await async
callbacks.
await [1, 2, 3].map(async v => {
await /* something */
return v * 2;
});
// [2, 4, 6]
Returns the highest element in the array
[-10, 0, 10].max();
// 10
['a', 'b', 'c'].max();
// 'c'
[].max();
// null
Returns the lowest element in the array
[-10, 0, 10].min();
// -10
['a', 'b', 'c'].min();
// 'a'
[].min();
// null
Returns false
if the array contains any elements.
[1, 2, 3].none();
// false
[].none();
// true
Matches two array using a callback and returns the joined results and unmatched results from both arrays.
const leftData = [
{ id: 1, name: 'Apples', groupId: 1 },
{ id: 2, name: 'Oranges', groupId: 1 },
{ id: 3, name: 'Cornflakes', groupId: 2 },
{ id: 4, name: 'Random', groupId: null }
];
const rightData = [
{ id: 1, name: 'Produce' },
{ id: 2, name: 'Grocery' },
{ id: 3, name: 'Confectionary' }
];
leftData.outerJoin(rightData, (l, r) => l.groupId === r.id);
// [
// {
// left: { id: 1, name: 'Apples', groupId: 1 },
// right: { id: 1, name: 'Produce' }
// },
// {
// left: { id: 2, name: 'Oranges', groupId: 1 },
// right: { id: 1, name: 'Produce' }
// },
// {
// left: { id: 3, name: 'Cornflakes', groupId: 2 },
// right: { id: 2, name: 'Grocery' }
// },
// {
// left: { id: 4, name: 'Random', groupId: null },
// right: null
// },
// {
// left: null,
// right: { id: 3, name: 'Confectionary' }
// }
// ];
Returns a new array, sorted by the result of a callback function.
[
{ name: 'Brian' },
{ name: 'Albert' },
{ name: 'Charlie' }
].sortBy(v => v.name);
// [
// { name: 'Albert' },
// { name: 'Brian' },
// { name: 'Charlie' }
// ]
Returns the total of all the elements in the array, optionally mapping them first with a callback
[1, 10, 100].sum();
// 111
[1, 2, 3, 4].sum(v => v % 2);
// 2
Returns a Record<K, V>
extracted from the array using callbacks.
Similar in functionality to groupBy, but returns a Record, and the last value with a matching key wins
[
{ name: 'Chloe', age: 19 },
{ name: 'Daniel', age: 16 },
{ name: 'Polly', age: 12 },
{ name: 'Lottie', age: 10 },
{ name: 'Theodore', age: 8 }
].toRecord(
k => k.name,
v => v.age
);
// {
// Chloe: 19,
// Daniel: 16,
// Polly: 12,
// Lottie: 10,
// Theodore: 8
// }
Returns only the values present in both arrays, using a comparer function if
supplied, or ===
if not.
[1, 2, 3].union([2, 3, 4]);
// [2, 3]
[
{ day: 1, month: 1, year: 1979 },
{ day: 2, month: 1, year: 1979 }
].union(
[
{ day: 2, month: 1, year: 1979 },
{ day: 3, month: 1, year: 1979 }
],
(a, b) => a.day === b.day && a.month === b.month && a.year === b.year
);
// [
// { day: 2, month: 1, year: 1979 }
// ]
Contributions welcome!