Documentation

Intro

Welcome to the Remeda documentation and API reference. Below, you’ll find the complete reference for all functions exported by Remeda.

Previous Versions

Are you using version 1.x.x? Visit our migration guide to help you transition to the latest version.


Determines whether all predicates returns true for the input data.

Data First
R.allPass(data, fns);
const isDivisibleBy3 = (x: number) => x % 3 === 0;
const isDivisibleBy4 = (x: number) => x % 4 === 0;
const fns = [isDivisibleBy3, isDivisibleBy4];
R.allPass(12, fns); // => true
R.allPass(8, fns); // => false
Data Last
R.allPass(fns)(data);
const isDivisibleBy3 = (x: number) => x % 3 === 0;
const isDivisibleBy4 = (x: number) => x % 4 === 0;
const fns = [isDivisibleBy3, isDivisibleBy4];
R.allPass(fns)(12); // => true
R.allPass(fns)(8); // => false

Determines whether any predicate returns true for the input data.

Data First
R.anyPass(data, fns);
const isDivisibleBy3 = (x: number) => x % 3 === 0;
const isDivisibleBy4 = (x: number) => x % 4 === 0;
const fns = [isDivisibleBy3, isDivisibleBy4];
R.anyPass(8, fns); // => true
R.anyPass(11, fns); // => false
Data Last
R.anyPass(fns)(data);
const isDivisibleBy3 = (x: number) => x % 3 === 0;
const isDivisibleBy4 = (x: number) => x % 4 === 0;
const fns = [isDivisibleBy3, isDivisibleBy4];
R.anyPass(fns)(8); // => true
R.anyPass(fns)(11); // => false

Split an array into groups the length of size. If array can't be split evenly, the final chunk will be the remaining elements.

Data First
R.chunk(array, size);
R.chunk(["a", "b", "c", "d"], 2); // => [['a', 'b'], ['c', 'd']]
R.chunk(["a", "b", "c", "d"], 3); // => [['a', 'b', 'c'], ['d']]
Data Last
R.chunk(size)(array);
R.chunk(2)(["a", "b", "c", "d"]); // => [['a', 'b'], ['c', 'd']]
R.chunk(3)(["a", "b", "c", "d"]); // => [['a', 'b', 'c'], ['d']]

Merge two or more arrays. This method does not change the existing arrays, but instead returns a new array, even if the other array is empty.

Data First
R.concat(data, other);
R.concat([1, 2, 3], ["a"]); // [1, 2, 3, 'a']
Data Last
R.concat(arr2)(arr1);
R.concat(["a"])([1, 2, 3]); // [1, 2, 3, 'a']

Categorize and count elements in an array using a defined callback function. The callback function is applied to each element in the array to determine its category and then counts how many elements fall into each category.

Data First
R.countBy(data, categorizationFn);
R.countBy(["a", "b", "c", "B", "A", "a"], R.toLowerCase()); //=> { a: 3, b: 2, c: 1 }
Data Last
R.countBy(categorizationFn)(data);
R.pipe(["a", "b", "c", "B", "A", "a"], R.countBy(R.toLowerCase())); //=> { a: 3, b: 2, c: 1 }

difference

Lazy
View source on GitHub

Excludes the values from other array. The output maintains the same order as the input. The inputs are treated as multi-sets/bags (multiple copies of items are treated as unique items).

Data First
R.difference(data, other);
R.difference([1, 2, 3, 4], [2, 5, 3]); // => [1, 4]
R.difference([1, 1, 2, 2], [1]); // => [1, 2, 2]
Data First
R.difference(other)(data);
R.pipe([1, 2, 3, 4], R.difference([2, 5, 3])); // => [1, 4]
R.pipe([1, 1, 2, 2], R.difference([1])); // => [1, 2, 2]

differenceWith

Lazy
View source on GitHub

Excludes the values from other array. Elements are compared by custom comparator isEquals.

Data First
R.differenceWith(array, other, isEquals);
R.differenceWith(
  [{ a: 1 }, { a: 2 }, { a: 3 }, { a: 4 }],
  [{ a: 2 }, { a: 5 }, { a: 3 }],
  R.equals,
); // => [{a: 1}, {a: 4}]
Data Last
R.differenceWith(other, isEquals)(array);
R.differenceWith(
  [{ a: 2 }, { a: 5 }, { a: 3 }],
  R.equals,
)([{ a: 1 }, { a: 2 }, { a: 3 }, { a: 4 }]); // => [{a: 1}, {a: 4}]
R.pipe(
  [{ a: 1 }, { a: 2 }, { a: 3 }, { a: 4 }, { a: 5 }, { a: 6 }], // only 4 iterations
  R.differenceWith([{ a: 2 }, { a: 3 }], R.equals),
  R.take(2),
); // => [{a: 1}, {a: 4}]

Removes first n elements from the array.

Data First
R.drop(array, n);
R.drop([1, 2, 3, 4, 5], 2); // => [3, 4, 5]
Data Last
R.drop(n)(array);
R.drop(2)([1, 2, 3, 4, 5]); // => [3, 4, 5]

dropFirstBy

View source on GitHub

Drop the first n items from data based on the provided ordering criteria. This allows you to avoid sorting the array before dropping the items. The complexity of this function is O(Nlogn) where N is the length of the array.

For the opposite operation (to keep n elements) see takeFirstBy.

Data First
R.dropFirstBy(data, n, ...rules);
R.dropFirstBy(["aa", "aaaa", "a", "aaa"], 2, (x) => x.length); // => ['aaa', 'aaaa']
Data Last
R.dropFirstBy(n, ...rules)(data);
R.pipe(
  ["aa", "aaaa", "a", "aaa"],
  R.dropFirstBy(2, (x) => x.length),
); // => ['aaa', 'aaaa']

Removes last n elements from the array.

Data First
R.dropLast(array, n);
R.dropLast([1, 2, 3, 4, 5], 2); // => [1, 2, 3]
Data Last
R.dropLast(n)(array);
R.dropLast(2)([1, 2, 3, 4, 5]); // => [1, 2, 3]

dropLastWhile

View source on GitHub

Removes elements from the end of the array until the predicate returns false.

The predicate is applied to each element in the array starting from the end and moving towards the beginning, until the predicate returns false. The returned array includes elements from the beginning of the array, up to and including the element that produced false for the predicate.

Data First
R.dropLastWhile(data, predicate);
R.dropLastWhile([1, 2, 10, 3, 4], (x) => x < 10); // => [1, 2, 10]
Data Last
R.dropLastWhile(predicate)(data);
R.pipe(
  [1, 2, 10, 3, 4],
  R.dropLastWhile((x) => x < 10),
); // => [1, 2, 10]

Removes elements from the beginning of the array until the predicate returns false.

The predicate is applied to each element in the array, until the predicate returns false. The returned array includes the rest of the elements, starting with the element that produced false for the predicate.

Data First
R.dropWhile(data, predicate);
R.dropWhile([1, 2, 10, 3, 4], (x) => x < 10); // => [10, 3, 4]
Data Last
R.dropWhile(predicate)(data);
R.pipe(
  [1, 2, 10, 3, 4],
  R.dropWhile((x) => x < 10),
); // => [10, 3, 4]

Creates a shallow copy of a portion of a given array, filtered down to just the elements from the given array that pass the test implemented by the provided function. Equivalent to Array.prototype.filter.

Data First
R.filter(data, predicate);
R.filter([1, 2, 3], (x) => x % 2 === 1); // => [1, 3]
Data Last
R.filter(predicate)(data);
R.pipe(
  [1, 2, 3],
  R.filter((x) => x % 2 === 1),
); // => [1, 3]

Returns the first element in the provided array that satisfies the provided testing function. If no values satisfy the testing function, undefined is returned.

Similar functions:

  • findLast - If you need the last element that satisfies the provided testing function.
  • findIndex - If you need the index of the found element in the array.
  • indexOf - If you need to find the index of a value.
  • includes - If you need to find if a value exists in an array.
  • some - If you need to find if any element satisfies the provided testing function.
  • filter - If you need to find all elements that satisfy the provided testing function.
Data First
R.find(data, predicate);
R.find([1, 3, 4, 6], (n) => n % 2 === 0); // => 4
Data Last
R.find(predicate)(data);
R.pipe(
  [1, 3, 4, 6],
  R.find((n) => n % 2 === 0),
); // => 4

Returns the index of the first element in an array that satisfies the provided testing function. If no elements satisfy the testing function, -1 is returned.

See also the find method, which returns the first element that satisfies the testing function (rather than its index).

Data First
R.findIndex(data, predicate);
R.findIndex([1, 3, 4, 6], (n) => n % 2 === 0); // => 2
Data Last
R.findIndex(predicate)(data);
R.pipe(
  [1, 3, 4, 6],
  R.findIndex((n) => n % 2 === 0),
); // => 2

Iterates the array in reverse order and returns the value of the first element that satisfies the provided testing function. If no elements satisfy the testing function, undefined is returned.

Similar functions:

  • find - If you need the first element that satisfies the provided testing function.
  • findLastIndex - If you need the index of the found element in the array.
  • lastIndexOf - If you need to find the index of a value.
  • includes - If you need to find if a value exists in an array.
  • some - If you need to find if any element satisfies the provided testing function.
  • filter - If you need to find all elements that satisfy the provided testing function.
Data First
R.findLast(data, predicate);
R.findLast([1, 3, 4, 6], (n) => n % 2 === 1); // => 3
Data Last
R.findLast(predicate)(data);
R.pipe(
  [1, 3, 4, 6],
  R.findLast((n) => n % 2 === 1),
); // => 3

findLastIndex

View source on GitHub

Iterates the array in reverse order and returns the index of the first element that satisfies the provided testing function. If no elements satisfy the testing function, -1 is returned.

See also findLast which returns the value of last element that satisfies the testing function (rather than its index).

Data First
R.findLastIndex(data, predicate);
R.findLastIndex([1, 3, 4, 6], (n) => n % 2 === 1); // => 1
Data Last
R.findLastIndex(fn)(items);
R.pipe(
  [1, 3, 4, 6],
  R.findLastIndex((n) => n % 2 === 1),
); // => 1

Gets the first element of array.

Data First
R.first(array);
R.first([1, 2, 3]); // => 1
R.first([]); // => undefined
Data Last
R.first()(array);
R.pipe(
  [1, 2, 4, 8, 16],
  R.filter((x) => x > 3),
  R.first(),
  (x) => x + 1,
); // => 5

Find the first element in the array that adheres to the order rules provided. This is a superset of what a typical maxBy or minBy function would do as it allows defining "tie-breaker" rules when values are equal, and allows comparing items using any logic. This function is equivalent to calling R.first(R.sortBy(...)) but runs at O(n) instead of O(nlogn).

Use nthBy if you need an element other that the first, or takeFirstBy if you more than just the first element.

Data Last
R.firstBy(...rules)(data);
const max = R.pipe([1, 2, 3], R.firstBy([R.identity(), "desc"])); // => 3;
const min = R.pipe([1, 2, 3], R.firstBy(R.identity())); // => 1;

const data = [{ a: "a" }, { a: "aa" }, { a: "aaa" }] as const;
const maxBy = R.pipe(data, R.firstBy([(item) => item.a.length, "desc"])); // => { a: "aaa" };
const minBy = R.pipe(
  data,
  R.firstBy((item) => item.a.length),
); // => { a: "a" };

const data = [
  { type: "cat", size: 1 },
  { type: "cat", size: 2 },
  { type: "dog", size: 3 },
] as const;
const multi = R.pipe(data, R.firstBy(R.prop("type"), [R.prop("size"), "desc"])); // => {type: "cat", size: 2}
Data First
R.firstBy(data, ...rules);
const max = R.firstBy([1, 2, 3], [R.identity(), "desc"]); // => 3;
const min = R.firstBy([1, 2, 3], R.identity()); // => 1;

const data = [{ a: "a" }, { a: "aa" }, { a: "aaa" }] as const;
const maxBy = R.firstBy(data, [(item) => item.a.length, "desc"]); // => { a: "aaa" };
const minBy = R.firstBy(data, (item) => item.a.length); // => { a: "a" };

const data = [
  { type: "cat", size: 1 },
  { type: "cat", size: 2 },
  { type: "dog", size: 3 },
] as const;
const multi = R.firstBy(data, R.prop("type"), [R.prop("size"), "desc"]); // => {type: "cat", size: 2}

Creates a new array with all sub-array elements concatenated into it recursively up to the specified depth. Equivalent to the built-in Array.prototype.flat method.

Data First
R.flat(data);
R.flat(data, depth);
R.flat([[1, 2], [3, 4], [5], [[6]]]); // => [1, 2, 3, 4, 5, [6]]
R.flat([[[1]], [[2]]], 2); // => [1, 2]
Data Last
R.flat()(data);
R.flat(depth)(data);
R.pipe([[1, 2], [3, 4], [5], [[6]]], R.flat()); // => [1, 2, 3, 4, 5, [6]]
R.pipe([[[1]], [[2]]], R.flat(2)); // => [1, 2]

flatMap

Lazy
View source on GitHub

Returns a new array formed by applying a given callback function to each element of the array, and then flattening the result by one level. It is identical to a map followed by a flat of depth 1 (flat(map(data, ...args))), but slightly more efficient than calling those two methods separately. Equivalent to Array.prototype.flatMap.

Data First
R.flatMap(data, callbackfn);
R.flatMap([1, 2, 3], (x) => [x, x * 10]); // => [1, 10, 2, 20, 3, 30]
Data Last
R.flatMap(callbackfn)(data);
R.pipe(
  [1, 2, 3],
  R.flatMap((x) => [x, x * 10]),
); // => [1, 10, 2, 20, 3, 30]

forEach

Lazy
View source on GitHub

Executes a provided function once for each array element. Equivalent to Array.prototype.forEach.

The dataLast version returns the original array (instead of not returning anything (void)) to allow using it in a pipe. When not used in a pipe the returned array is equal to the input array (by reference), and not a shallow copy of it!

Data First
R.forEach(data, callbackfn);
R.forEach([1, 2, 3], (x) => {
  console.log(x);
});
Data Last
R.forEach(callbackfn)(data);
R.pipe(
  [1, 2, 3],
  R.forEach((x) => {
    console.log(x);
  }),
); // => [1, 2, 3]

Groups the elements of a given iterable according to the string values returned by a provided callback function. The returned object has separate properties for each group, containing arrays with the elements in the group. Unlike the built in Object.groupBy this function also allows the callback to return undefined in order to exclude the item from being added to any group.

Data First
R.groupBy(data, callbackfn);
R.groupBy([{ a: "cat" }, { a: "dog" }] as const, R.prop("a")); // => {cat: [{a: 'cat'}], dog: [{a: 'dog'}]}
R.groupBy([0, 1], (x) => (x % 2 === 0 ? "even" : undefined)); // => {even: [0]}
Data Last
R.groupBy(callbackfn)(data);
R.pipe([{ a: "cat" }, { a: "dog" }] as const, R.groupBy(R.prop("a"))); // => {cat: [{a: 'cat'}], dog: [{a: 'dog'}]}
R.pipe(
  [0, 1],
  R.groupBy((x) => (x % 2 === 0 ? "even" : undefined)),
); // => {even: [0]}

Checks if the given array has at least the defined number of elements. When the minimum used is a literal (e.g. 3) the output is refined accordingly so that those indices are defined when accessing the array even when using typescript's 'noUncheckedIndexAccess'.

Data First
R.hasAtLeast(data, minimum);
R.hasAtLeast([], 4); // => false

const data: number[] = [1, 2, 3, 4];
R.hasAtLeast(data, 1); // => true
data[0]; // 1, with type `number`
Data Last
R.hasAtLeast(minimum)(data);
R.pipe([], R.hasAtLeast(4)); // => false

const data = [[1, 2], [3], [4, 5]];
R.pipe(
  data,
  R.filter(R.hasAtLeast(2)),
  R.map(([, second]) => second),
); // => [2,5], with type `number[]`

Converts a list of objects into an object indexing the objects by the given key.

There are several other functions that could be used to build an object from an array:

  • fromKeys - Builds an object from an array of keys and a mapper for values.
  • pullObject - Builds an object from an array of items with mappers for both keys and values.
  • fromEntries - Builds an object from an array of key-value pairs.
  • mapToObj - Builds an object from an array of items and a single mapper for key-value pairs. Refer to the docs for more details.
Data First
R.indexBy(array, fn);
R.indexBy(["one", "two", "three"], (x) => x.length); // => {3: 'two', 5: 'three'}
Data Last
R.indexBy(fn)(array);
R.pipe(
  ["one", "two", "three"],
  R.indexBy((x) => x.length),
); // => {3: 'two', 5: 'three'}

intersection

Lazy
View source on GitHub

Returns a list of elements that exist in both array. The output maintains the same order as the input. The inputs are treated as multi-sets/bags (multiple copies of items are treated as unique items).

Data First
R.intersection(data, other);
R.intersection([1, 2, 3], [2, 3, 5]); // => [2, 3]
R.intersection([1, 1, 2, 2], [1]); // => [1]
Data First
R.intersection(other)(data);
R.pipe([1, 2, 3], R.intersection([2, 3, 5])); // => [2, 3]
R.pipe([1, 1, 2, 2], R.intersection([1])); // => [1]

intersectionWith

Lazy
View source on GitHub

Returns a list of intersecting values based on a custom comparator function that compares elements of both arrays.

Data First
R.intersectionWith(array, other, comparator);
R.intersectionWith(
  [
    { id: 1, name: "Ryan" },
    { id: 3, name: "Emma" },
  ],
  [3, 5],
  (a, b) => a.id === b,
); // => [{ id: 3, name: 'Emma' }]
Data Last
R.intersectionWith(other, comparator)(array);
R.intersectionWith(
  [3, 5],
  (a, b) => a.id === b,
)([
  { id: 1, name: "Ryan" },
  { id: 3, name: "Emma" },
]); // => [{ id: 3, name: 'Emma' }]

Joins the elements of the array by: casting them to a string and concatenating them one to the other, with the provided glue string in between every two elements.

When called on a tuple and with stricter item types (union of literal values, the result is strictly typed to the tuples shape and it's item types).

Data First
R.join(data, glue);
R.join([1, 2, 3], ","); // => "1,2,3" (typed `string`)
R.join(["a", "b", "c"], ""); // => "abc" (typed `string`)
R.join(["hello", "world"] as const, " "); // => "hello world" (typed `hello world`)
Data Last
R.join(glue)(data);
R.pipe([1, 2, 3], R.join(",")); // => "1,2,3" (typed `string`)
R.pipe(["a", "b", "c"], R.join("")); // => "abc" (typed `string`)
R.pipe(["hello", "world"] as const, R.join(" ")); // => "hello world" (typed `hello world`)

Gets the last element of array.

Data First
R.last(array);
R.last([1, 2, 3]); // => 3
R.last([]); // => undefined
Data Last
R.last()(array);
R.pipe(
  [1, 2, 4, 8, 16],
  R.filter((x) => x > 3),
  R.last(),
  (x) => x + 1,
); // => 17

Counts values of the collection or iterable.

Data First
R.length(array);
R.length([1, 2, 3]); // => 3
Data Last
R.length()(array);
R.pipe([1, 2, 3], R.length()); // => 3

Creates a new array populated with the results of calling a provided function on every element in the calling array. Equivalent to Array.prototype.map.

Data First
R.map(data, callbackfn);
R.map([1, 2, 3], R.multiply(2)); // => [2, 4, 6]
R.map([0, 0], R.add(1)); // => [1, 1]
R.map([0, 0], (value, index) => value + index); // => [0, 1]
Data Last
R.map(callbackfn)(data);
R.pipe([1, 2, 3], R.map(R.multiply(2))); // => [2, 4, 6]
R.pipe([0, 0], R.map(R.add(1))); // => [1, 1]
R.pipe(
  [0, 0],
  R.map((value, index) => value + index),
); // => [0, 1]

Map each element of an array into an object using a defined callback function.

There are several other functions that could be used to build an object from an array:

  • fromKeys - Builds an object from an array of keys and a mapper for values.
  • indexBy - Builds an object from an array of values and a mapper for keys.
  • pullObject - Builds an object from an array of items with mappers for both keys and values.
  • fromEntries - Builds an object from an array of key-value pairs. Refer to the docs for more details.
Data First
R.mapToObj(array, fn);
R.mapToObj([1, 2, 3], (x) => [String(x), x * 2]); // => {1: 2, 2: 4, 3: 6}
Data Last
R.mapToObj(fn)(array);
R.pipe(
  [1, 2, 3],
  R.mapToObj((x) => [String(x), x * 2]),
); // => {1: 2, 2: 4, 3: 6}

mapWithFeedback

Lazy
View source on GitHub

Applies a function on each element of the array, using the result of the previous application, and returns an array of the successively computed values.

Data First
R.mapWithFeedback(data, callbackfn, initialValue);
R.mapWithFeedback([1, 2, 3, 4, 5], (prev, x) => prev + x, 100); // => [101, 103, 106, 110, 115]
Data Last
R.mapWithFeedback(callbackfn, initialValue)(data);
R.pipe(
  [1, 2, 3, 4, 5],
  R.mapWithFeedback((prev, x) => prev + x, 100),
); // => [101, 103, 106, 110, 115]

Returns the mean of the elements of an array using the provided predicate.

Data Last
R.meanBy(fn)(array);
R.pipe(
  [{ a: 5 }, { a: 1 }, { a: 3 }],
  R.meanBy((x) => x.a),
); // 3
Data First
R.meanBy(array, fn);
R.meanBy([{ a: 5 }, { a: 1 }, { a: 3 }], (x) => x.a); // 3

Merges a list of objects into a single object.

Data First
R.mergeAll(objects);
R.mergeAll([{ a: 1, b: 1 }, { b: 2, c: 3 }, { d: 10 }]); // => { a: 1, b: 2, c: 3, d: 10 }
R.mergeAll([]); // => {}

Retrieves the element that would be at the given index if the array were sorted according to specified rules. This function uses the QuickSelect algorithm running at an average complexity of O(n). Semantically it is equivalent to sortBy(data, ...rules).at(index) which would run at O(nlogn).

See also firstBy which provides an even more efficient algorithm and a stricter return type, but only for index === 0. See takeFirstBy to get all the elements up to and including index.

Data First
R.nthBy(data, index, ...rules);
R.nthBy([2, 1, 4, 5, 3], 2, identity()); // => 3
Data Last
R.nthBy(index, ...rules)(data);
R.pipe([2, 1, 4, 5, 3], R.nthBy(2, identity())); // => 3

Returns the first and only element of array, or undefined otherwise.

Data First
R.only(array);
R.only([]); // => undefined
R.only([1]); // => 1
R.only([1, 2]); // => undefined
Data Last
R.only()(array);
R.pipe([], R.only()); // => undefined
R.pipe([1], R.only()); // => 1
R.pipe([1, 2], R.only()); // => undefined

Splits a collection into two groups, the first of which contains elements the predicate type guard passes, and the second one containing the rest.

Data First
R.partition(data, predicate);
R.partition(["one", "two", "forty two"], (x) => x.length === 3); // => [['one', 'two'], ['forty two']]
Data Last
R.partition(predicate)(data);
R.pipe(
  ["one", "two", "forty two"],
  R.partition((x) => x.length === 3),
); // => [['one', 'two'], ['forty two']]

Returns a list of numbers from start (inclusive) to end (exclusive).

Data First
range(start, end);
R.range(1, 5); // => [1, 2, 3, 4]
Data Last
range(end)(start);
R.range(5)(1); // => [1, 2, 3, 4]

Calculates the rank of an item in an array based on rules. The rank is the position where the item would appear in the sorted array. This function provides an efficient way to determine the rank in O(n) time, compared to O(nlogn) for the equivalent sortedIndex(sortBy(data, ...rules), item).

Data First
R.rankBy(data, item, ...rules);
const DATA = [{ a: 5 }, { a: 1 }, { a: 3 }] as const;
R.rankBy(DATA, 0, R.prop("a")); // => 0
R.rankBy(DATA, 1, R.prop("a")); // => 1
R.rankBy(DATA, 2, R.prop("a")); // => 1
R.rankBy(DATA, 3, R.prop("a")); // => 2
Data Last
R.rankBy(item, ...rules)(data);
const DATA = [{ a: 5 }, { a: 1 }, { a: 3 }] as const;
R.pipe(DATA, R.rankBy(0, R.prop("a"))); // => 0
R.pipe(DATA, R.rankBy(1, R.prop("a"))); // => 1
R.pipe(DATA, R.rankBy(2, R.prop("a"))); // => 1
R.pipe(DATA, R.rankBy(3, R.prop("a"))); // => 2

Executes a user-supplied "reducer" callback function on each element of the array, in order, passing in the return value from the calculation on the preceding element. The final result of running the reducer across all elements of the array is a single value. Equivalent to Array.prototype.reduce.

Data First
R.reduce(data, callbackfn, initialValue);
R.reduce([1, 2, 3, 4, 5], (acc, x) => acc + x, 100); // => 115
Data Last
R.reduce(fn, initialValue)(array);
R.pipe(
  [1, 2, 3, 4, 5],
  R.reduce((acc, x) => acc + x, 100),
); // => 115

Reverses array.

Data First
R.reverse(arr);
R.reverse([1, 2, 3]); // [3, 2, 1]
Data Last
R.reverse()(array);
R.reverse()([1, 2, 3]); // [3, 2, 1]

Returns a random subset of size sampleSize from array.

Maintains and infers most of the typing information that could be passed along to the output. This means that when using tuples, the output will be a tuple too, and when using literals, those literals would be preserved.

The items in the result are kept in the same order as they are in the input. If you need to get a shuffled response you can pipe the shuffle function after this one.

Data First
R.sample(array, sampleSize);
R.sample(["hello", "world"], 1); // => ["hello"] // typed string[]
R.sample(["hello", "world"] as const, 1); // => ["world"] // typed ["hello" | "world"]
Data Last
R.sample(sampleSize)(array);
R.sample(1)(["hello", "world"]); // => ["hello"] // typed string[]
R.sample(1)(["hello", "world"] as const); // => ["world"] // typed ["hello" | "world"]

Shuffles the input array, returning a new array with the same elements in a random order.

Data First
R.shuffle(array);
R.shuffle([4, 2, 7, 5]); // => [7, 5, 4, 2]
Data Last
R.shuffle()(array);
R.pipe([4, 2, 7, 5], R.shuffle()); // => [7, 5, 4, 2]

Sorts an array. The comparator function should accept two values at a time and return a negative number if the first value is smaller, a positive number if it's larger, and zero if they are equal. Sorting is based on a native sort function.

Data First
R.sort(items, cmp);
R.sort([4, 2, 7, 5], (a, b) => a - b); // => [2, 4, 5, 7]
Data Last
R.sort(cmp)(items);
R.pipe(
  [4, 2, 7, 5],
  R.sort((a, b) => a - b),
); // => [2, 4, 5, 7]

Sorts data using the provided ordering rules. The sort is done via the native Array.prototype.sort but is performed on a shallow copy of the array to avoid mutating the original data.

There are several other functions that take order rules and bypass the need to sort the array first (in O(nlogn) time):

  • firstBy === first(sortBy(data, ...rules)), O(n).
  • takeFirstBy === take(sortBy(data, ...rules), k), O(nlogk).
  • dropFirstBy === drop(sortBy(data, ...rules), k), O(nlogk).
  • nthBy === sortBy(data, ...rules).at(k), O(n).
  • rankBy === sortedIndex(sortBy(data, ...rules), item), O(n). Refer to the docs for more details.
Data Last
R.sortBy(...rules)(data);
R.pipe([{ a: 1 }, { a: 3 }, { a: 7 }, { a: 2 }], R.sortBy(R.prop("a"))); // => [{ a: 1 }, { a: 2 }, { a: 3 }, { a: 7 }]
Data First
R.sortBy(data, ...rules);
R.sortBy([{ a: 1 }, { a: 3 }, { a: 7 }, { a: 2 }], prop("a")); // => [{ a: 1 }, { a: 2 }, { a: 3 }, { a: 7 }]
R.sortBy(
  [
    { color: "red", weight: 2 },
    { color: "blue", weight: 3 },
    { color: "green", weight: 1 },
    { color: "purple", weight: 1 },
  ],
  [prop("weight"), "asc"],
  prop("color"),
); // => [
//   {color: 'green', weight: 1},
//   {color: 'purple', weight: 1},
//   {color: 'red', weight: 2},
//   {color: 'blue', weight: 3},
// ]

sortedIndex

View source on GitHub

Find the insertion position (index) of an item in an array with items sorted in ascending order; so that splice(sortedIndex, 0, item) would result in maintaining the array's sort-ness. The array can contain duplicates. If the item already exists in the array the index would be of the first occurrence of the item.

Runs in O(logN) time.

Data First
R.sortedIndex(data, item);
R.sortedIndex(["a", "a", "b", "c", "c"], "c"); // => 3
Data Last
R.sortedIndex(item)(data);
R.pipe(["a", "a", "b", "c", "c"], R.sortedIndex("c")); // => 3

sortedIndexBy

View source on GitHub

Find the insertion position (index) of an item in an array with items sorted in ascending order using a value function; so that splice(sortedIndex, 0, item) would result in maintaining the arrays sort- ness. The array can contain duplicates. If the item already exists in the array the index would be of the first occurrence of the item.

Runs in O(logN) time.

See also:

  • findIndex - scans a possibly unsorted array in-order (linear search).
  • sortedIndex - like this function, but doesn't take a callbackfn.
  • sortedLastIndexBy - like this function, but finds the last suitable index.
  • sortedLastIndex - like sortedIndex, but finds the last suitable index.
  • rankBy - scans a possibly unsorted array in-order, returning the index based on a sorting criteria.
Data First
R.sortedIndexBy(data, item, valueFunction);
R.sortedIndexBy([{ age: 20 }, { age: 22 }], { age: 21 }, prop("age")); // => 1

sortedIndexWith

View source on GitHub

Performs a binary search for the index of the item at which the predicate stops returning true. This function assumes that the array is "sorted" in regards to the predicate, meaning that running the predicate as a mapper on it would result in an array [...true[], ...false[]]. This stricter requirement from the predicate provides us 2 benefits over findIndex which does a similar thing:

  1. It would run at O(logN) time instead of O(N) time.
  2. It always returns a value (it would return data.length if the predicate returns true for all items).

This function is the basis for all other sortedIndex functions which search for a specific item in a sorted array, and it could be used to perform similar efficient searches.

See also:

  • findIndex - scans a possibly unsorted array in-order (linear search).
  • rankBy - scans a possibly unsorted array in-order, returning the index based on a sorting criteria.
Data First
R.sortedIndexWith(data, predicate);
R.sortedIndexWith(["a", "ab", "abc"], (item) => item.length < 2); // => 1
Data Last
R.sortedIndexWith(predicate)(data);
R.pipe(
  ["a", "ab", "abc"],
  R.sortedIndexWith((item) => item.length < 2),
); // => 1

sortedLastIndex

View source on GitHub

Find the insertion position (index) of an item in an array with items sorted in ascending order; so that splice(sortedIndex, 0, item) would result in maintaining the array's sort-ness. The array can contain duplicates. If the item already exists in the array the index would be of the last occurrence of the item.

Runs in O(logN) time.

Data First
R.sortedLastIndex(data, item);
R.sortedLastIndex(["a", "a", "b", "c", "c"], "c"); // => 5
Data Last
R.sortedLastIndex(item)(data);
R.pipe(["a", "a", "b", "c", "c"], sortedLastIndex("c")); // => 5

sortedLastIndexBy

View source on GitHub

Find the insertion position (index) of an item in an array with items sorted in ascending order using a value function; so that splice(sortedIndex, 0, item) would result in maintaining the arrays sort- ness. The array can contain duplicates. If the item already exists in the array the index would be of the last occurrence of the item.

Runs in O(logN) time.

See also:

  • findIndex - scans a possibly unsorted array in-order (linear search).
  • sortedLastIndex - a simplified version of this function, without a callbackfn.
  • sortedIndexBy - like this function, but returns the first suitable index.
  • sortedIndex - like sortedLastIndex but without a callbackfn.
  • rankBy - scans a possibly unsorted array in-order, returning the index based on a sorting criteria.
Data First
R.sortedLastIndexBy(data, item, valueFunction);
R.sortedLastIndexBy([{ age: 20 }, { age: 22 }], { age: 21 }, prop("age")); // => 1
Data Last
R.sortedLastIndexBy(item, valueFunction)(data);
R.pipe([{ age: 20 }, { age: 22 }], sortedLastIndexBy({ age: 21 }, prop("age"))); // => 1

Removes elements from an array and, inserts new elements in their place.

Data First
R.splice(items, start, deleteCount, replacement);
R.splice([1, 2, 3, 4, 5, 6, 7, 8], 2, 3, []); //=> [1,2,6,7,8]
R.splice([1, 2, 3, 4, 5, 6, 7, 8], 2, 3, [9, 10]); //=> [1,2,9,10,6,7,8]
Data Last
R.splice(start, deleteCount, replacement)(items);
R.pipe([1, 2, 3, 4, 5, 6, 7, 8], R.splice(2, 3, [])); // => [1,2,6,7,8]
R.pipe([1, 2, 3, 4, 5, 6, 7, 8], R.splice(2, 3, [9, 10])); // => [1,2,9,10,6,7,8]

Splits a given array at a given index.

Data First
R.splitAt(array, index);
R.splitAt([1, 2, 3], 1); // => [[1], [2, 3]]
R.splitAt([1, 2, 3, 4, 5], -1); // => [[1, 2, 3, 4], [5]]
Data Last
R.splitAt(index)(array);
R.splitAt(1)([1, 2, 3]); // => [[1], [2, 3]]
R.splitAt(-1)([1, 2, 3, 4, 5]); // => [[1, 2, 3, 4], [5]]

Splits a given array at the first index where the given predicate returns true.

Data First
R.splitWhen(array, fn);
R.splitWhen([1, 2, 3], (x) => x === 2); // => [[1], [2, 3]]
Data Last
R.splitWhen(fn)(array);
R.splitWhen((x) => x === 2)([1, 2, 3]); // => [[1], [2, 3]]

Returns the sum of the elements of an array using the provided mapper.

Works for both number and bigint mappers, but not mappers that return both types.

IMPORTANT: The result for empty arrays would be 0 (number) regardless of the type of the mapper; to avoid adding this to the return type for cases where the array is known to be non-empty you can use hasAtLeast or isEmpty to guard against this case.

Data Last
R.sumBy(fn)(array);
R.pipe(
  [{ a: 5 }, { a: 1 }, { a: 3 }],
  R.sumBy((x) => x.a),
); // 9

R.pipe(
  [{ a: 5n }, { a: 1n }, { a: 3n }],
  R.sumBy((x) => x.a),
); // 9n
Data First
R.sumBy(array, fn);
R.sumBy([{ a: 5 }, { a: 1 }, { a: 3 }], (x) => x.a); // 9
R.sumBy([{ a: 5n }, { a: 1n }, { a: 3n }], (x) => x.a); // 9n

swapIndices

View source on GitHub

Swaps the positions of two elements in an array or string at the provided indices.

Negative indices are supported and would be treated as an offset from the end of the array. The resulting type thought would be less strict than when using positive indices.

If either index is out of bounds the result would be a shallow copy of the input, as-is.

Data First
swapIndices(data, index1, index2);
swapIndices(["a", "b", "c"], 0, 1); // => ['b', 'a', 'c']
swapIndices(["a", "b", "c"], 1, -1); // => ['a', 'c', 'b']
swapIndices("abc", 0, 1); // => 'bac'
Data Last
swapIndices(index1, index2)(data);
swapIndices(0, 1)(["a", "b", "c"]); // => ['b', 'a', 'c']
swapIndices(0, -1)("abc"); // => 'cba'

Returns the first n elements of array.

Data First
R.take(array, n);
R.take([1, 2, 3, 4, 3, 2, 1], 3); // => [1, 2, 3]
Data Last
R.take(n)(array);
R.pipe([1, 2, 3, 4, 3, 2, 1], R.take(n)); // => [1, 2, 3]

takeFirstBy

View source on GitHub

Take the first n items from data based on the provided ordering criteria. This allows you to avoid sorting the array before taking the items. The complexity of this function is O(Nlogn) where N is the length of the array.

For the opposite operation (to drop n elements) see dropFirstBy.

Data First
R.takeFirstBy(data, n, ...rules);
R.takeFirstBy(["aa", "aaaa", "a", "aaa"], 2, (x) => x.length); // => ['a', 'aa']
Data Last
R.takeFirstBy(n, ...rules)(data);
R.pipe(
  ["aa", "aaaa", "a", "aaa"],
  R.takeFirstBy(2, (x) => x.length),
); // => ['a', 'aa']

Takes the last n elements from the array.

Data First
R.takeLast(array, n);
R.takeLast([1, 2, 3, 4, 5], 2); // => [4, 5]
Data Last
R.takeLast(n)(array);
R.takeLast(2)([1, 2, 3, 4, 5]); // => [4, 5]

takeLastWhile

View source on GitHub

Returns elements from the end of the array until the predicate returns false. The returned elements will be in the same order as in the original array.

Data First
R.takeLastWhile(data, predicate);
R.takeLastWhile([1, 2, 10, 3, 4, 5], (x) => x < 10); // => [3, 4, 5]
Data Last
R.takeLastWhile(predicate)(data);
R.pipe(
  [1, 2, 10, 3, 4, 5],
  R.takeLastWhile((x) => x < 10),
); // => [3, 4, 5]

Returns elements from the array until predicate returns false.

Data First
R.takeWhile(data, predicate);
R.takeWhile([1, 2, 3, 4, 3, 2, 1], (x) => x !== 4); // => [1, 2, 3]
Data Last
R.takeWhile(predicate)(data);
R.pipe(
  [1, 2, 3, 4, 3, 2, 1],
  R.takeWhile((x) => x !== 4),
); // => [1, 2, 3]

Calls an input function n times, returning an array containing the results of those function calls.

fn is passed one argument: The current value of n, which begins at 0 and is gradually incremented to n - 1.

Data First
R.times(count, fn);
R.times(5, R.identity()); //=> [0, 1, 2, 3, 4]
Data Last
R.times(fn)(count);
R.times(R.identity())(5); //=> [0, 1, 2, 3, 4]

Returns a new array containing only one copy of each element in the original list. Elements are compared by reference using Set.

Data First
R.unique(array);
R.unique([1, 2, 2, 5, 1, 6, 7]); // => [1, 2, 5, 6, 7]
Data Last
R.unique()(array);
R.pipe(
  [1, 2, 2, 5, 1, 6, 7], // only 4 iterations
  R.unique(),
  R.take(3),
); // => [1, 2, 5]

uniqueBy

Lazy
View source on GitHub

Returns a new array containing only one copy of each element in the original list transformed by a function. Elements are compared by reference using Set.

Data First
R.uniqueBy(data, keyFunction);
R.uniqueBy(
  [{ n: 1 }, { n: 2 }, { n: 2 }, { n: 5 }, { n: 1 }, { n: 6 }, { n: 7 }],
  (obj) => obj.n,
); // => [{n: 1}, {n: 2}, {n: 5}, {n: 6}, {n: 7}]
Data Last
R.uniqueBy(keyFunction)(data);
R.pipe(
  [{ n: 1 }, { n: 2 }, { n: 2 }, { n: 5 }, { n: 1 }, { n: 6 }, { n: 7 }], // only 4 iterations
  R.uniqueBy((obj) => obj.n),
  R.take(3),
); // => [{n: 1}, {n: 2}, {n: 5}]

uniqueWith

Lazy
View source on GitHub

Returns a new array containing only one copy of each element in the original list. Elements are compared by custom comparator isEquals.

Data First
R.uniqueWith(array, isEquals);
R.uniqueWith(
  [{ a: 1 }, { a: 2 }, { a: 2 }, { a: 5 }, { a: 1 }, { a: 6 }, { a: 7 }],
  R.equals,
); // => [{a: 1}, {a: 2}, {a: 5}, {a: 6}, {a: 7}]
Data Last
R.uniqueWith(isEquals)(array);
R.uniqueWith(R.equals)([
  { a: 1 },
  { a: 2 },
  { a: 2 },
  { a: 5 },
  { a: 1 },
  { a: 6 },
  { a: 7 },
]); // => [{a: 1}, {a: 2}, {a: 5}, {a: 6}, {a: 7}]
R.pipe(
  [{ a: 1 }, { a: 2 }, { a: 2 }, { a: 5 }, { a: 1 }, { a: 6 }, { a: 7 }], // only 4 iterations
  R.uniqueWith(R.equals),
  R.take(3),
); // => [{a: 1}, {a: 2}, {a: 5}]

Creates a new list from two supplied lists by pairing up equally-positioned items. The length of the returned list will match the shortest of the two inputs.

Data First
R.zip(first, second);
R.zip([1, 2], ["a", "b"]); // => [[1, 'a'], [2, 'b']]
Data Last
R.zip(second)(first);
R.zip(["a", "b"])([1, 2]); // => [[1, 'a'], [2, 'b']]

Creates a new list from two supplied lists by calling the supplied function with the same-positioned element from each list.

R.zipWith(fn)(first, second);
R.zipWith((a: string, b: string) => a + b)(["1", "2", "3"], ["a", "b", "c"]); // => ['1a', '2b', '3c']
Data Last
R.zipWith(second, fn)(first);
R.pipe(
  ["1", "2", "3"],
  R.zipWith(["a", "b", "c"], (a, b) => a + b),
); // => ['1a', '2b', '3c']
Data First
R.zipWith(first, second, fn);
R.zipWith(["1", "2", "3"], ["a", "b", "c"], (a, b) => a + b); // => ['1a', '2b', '3c']

conditional

View source on GitHub

Executes a transformer function based on the first matching predicate, functioning like a series of if...else if... statements. It sequentially evaluates each case and, upon finding a truthy predicate, runs the corresponding transformer, and returns, ignoring any further cases, even if they would match.

For simpler cases you should also consider using when instead.

!IMPORTANT! - Unlike similar implementations in frameworks like Lodash and Ramda, the Remeda implementation does NOT return a default/fallback undefined value when none of the cases match; and instead will throw an exception in those cases. To add a default case use the conditional.defaultCase helper as the final case of your implementation. By default it returns undefined, but could be provided a transformer in order to return something else.

Due to TypeScript's inability to infer the result of negating a type- predicate we can't refine the types used in subsequent cases based on previous conditions. Using a switch (true) statement or ternary operators is recommended for more precise type control when such type narrowing is needed.

Data Last
R.conditional(...cases)(data);
const nameOrId = 3 as string | number;
R.pipe(
  nameOrId,
  R.conditional(
    [R.isString, (name) => `Hello ${name}`],
    [R.isNumber, (id) => `Hello ID: ${id}`],
    R.conditional.defaultCase(
      (something) => `Hello something (${JSON.stringify(something)})`,
    ),
  ),
); //=> 'Hello ID: 3'
Data First
R.conditional(data, ...cases);
const nameOrId = 3 as string | number;
R.conditional(
  nameOrId,
  [R.isString, (name) => `Hello ${name}`],
  [R.isNumber, (id) => `Hello ID: ${id}`],
  R.conditional.defaultCase(
    (something) => `Hello something (${JSON.stringify(something)})`,
  ),
); //=> 'Hello ID: 3'

constant

View source on GitHub

A function that takes any arguments and returns the provided value on every invocation. This is useful to provide trivial implementations for APIs or in combination with a ternary or other conditional execution to allow to short- circuit more complex implementations for a specific case.

Notice that this is a dataLast impl where the function needs to be invoked to get the "do nothing" function.

See also: doNothing - A function that doesn't return anything. identity - A function that returns the first argument it receives.

Data Last
R.constant(value);
R.map([1, 2, 3], R.constant("a")); // => ['a', 'a', 'a']
R.map([1, 2, 3], isDemoMode ? R.add(1) : R.constant(0)); // => [2, 3, 4] or [0, 0, 0]

debounce

View source on GitHub

Wraps func with a debouncer object that "debounces" (delays) invocations of the function during a defined cool-down period (waitMs). It can be configured to invoke the function either at the start of the cool-down period, the end of it, or at both ends (timing). It can also be configured to allow invocations during the cool-down period (maxWaitMs). It stores the latest call's arguments so they could be used at the end of the cool-down period when invoking func (if configured to invoke the function at the end of the cool-down period). It stores the value returned by func whenever its invoked. This value is returned on every call, and is accessible via the cachedValue property of the debouncer. Its important to note that the value might be different from the value that would be returned from running func with the current arguments as it is a cached value from a previous invocation. Important: The cool-down period defines the minimum between two invocations, and not the maximum. The period will be extended each time a call is made until a full cool-down period has elapsed without any additional calls.

! DEPRECATED: This implementation of debounce is known to have issues and might not behave as expected. It should be replaced with the funnel utility instead. The test file funnel.remeda-debounce.test.ts offers a reference implementation that replicates debounce via funnel!

Data First
R.debounce(func, options);
const debouncer = debounce(identity(), { timing: "trailing", waitMs: 1000 });
const result1 = debouncer.call(1); // => undefined
const result2 = debouncer.call(2); // => undefined
// after 1 second
const result3 = debouncer.call(3); // => 2
// after 1 second
debouncer.cachedValue; // => 3

doNothing

View source on GitHub

A function that takes any arguments and does nothing with them. This is useful as a placeholder for any function or API that requires a void function (a function that doesn't return a value). This could also be used in combination with a ternary or other conditional execution to allow disabling a function call for a specific case.

Notice that this is a dataLast impl where the function needs to be invoked to get the "do nothing" function.

See also:

  • constant - A function that ignores it's arguments and returns the same value on every invocation.
  • identity - A function that returns the first argument it receives.
Data Last
R.doNothing();
myApi({ onSuccess: handleSuccess, onError: R.doNothing() });
myApi({ onSuccess: isDemoMode ? R.doNothing() : handleSuccess });

Creates a funnel that controls the timing and execution of callback. Its main purpose is to manage multiple consecutive (usually fast-paced) calls, reshaping them according to a defined batching strategy and timing policy. This is useful when handling uncontrolled call rates, such as DOM events or network traffic. It can implement strategies like debouncing, throttling, batching, and more.

An optional reducer function can be provided to allow passing data to the callback via calls to call (otherwise the signature of call takes no arguments).

Typing is inferred from callbacks param, and from the rest params that the optional reducer function accepts. Use explicit types for these to ensure that everything else is well-typed.

Notice that this function constructs a funnel object, and does not execute anything when called. The returned object should be used to execute the funnel via the its call method.

  • Debouncing: use minQuietPeriodMs and any triggerAt.
  • Throttling: use minGapMs and triggerAt: "start" or "both".
  • Batching: See the reference implementation in funnel.reference-batch.test.ts.
R.funnel(callback, options);
const debouncer = R.funnel(
  () => {
    console.log("Callback executed!");
  },
  { minQuietPeriodMs: 100 },
);
debouncer.call();
debouncer.call();

const throttle = R.funnel(
  () => {
    console.log("Callback executed!");
  },
  { minGapMs: 100, triggerAt: "start" },
);
throttle.call();
throttle.call();

identity

View source on GitHub