Adds two numbers.
Data First
R.add(value, addend);
R.add(10, 5); // => 15
R.add(10, -5); // => 5
R.reduce([1, 2, 3, 4], R.add, 0); // => 10
Data Last
R.add(addend)(value);
R.add(5)(10); // => 15
R.add(-5)(10); // => 5
R.map([1, 2, 3, 4], R.add(1)); // => [2, 3, 4, 5]
Rounds up a given number to a specific precision.
If you'd like to round up to an integer (i.e. use this function with constant precision === 0
),
use Math.ceil
instead, as it won't incur the additional library overhead.
Data First
R.ceil(value, precision);
R.ceil(123.9876, 3); // => 123.988
R.ceil(483.22243, 1); // => 483.3
R.ceil(8541, -1); // => 8550
R.ceil(456789, -3); // => 457000
Data Last
R.ceil(precision)(value);
R.ceil(3)(123.9876); // => 123.988
R.ceil(1)(483.22243); // => 483.3
R.ceil(-1)(8541); // => 8550
R.ceil(-3)(456789); // => 457000
Clamp the given value within the inclusive min and max bounds.
Data First
R.clamp(value, { min, max });
clamp(10, { min: 20 }); // => 20
clamp(10, { max: 5 }); // => 5
clamp(10, { max: 20, min: 5 }); // => 10
Data Last
R.clamp({ min, max })(value);
clamp({ min: 20 })(10); // => 20
clamp({ max: 5 })(10); // => 5
clamp({ max: 20, min: 5 })(10); // => 10
Divides two numbers.
Data First
R.divide(value, divisor);
R.divide(12, 3); // => 4
R.reduce([1, 2, 3, 4], R.divide, 24); // => 1
Data Last
R.divide(divisor)(value);
R.divide(3)(12); // => 4
R.map([2, 4, 6, 8], R.divide(2)); // => [1, 2, 3, 4]
Rounds down a given number to a specific precision.
If you'd like to round down to an integer (i.e. use this function with constant precision === 0
),
use Math.floor
instead, as it won't incur the additional library overhead.
Data First
R.floor(value, precision);
R.floor(123.9876, 3); // => 123.987
R.floor(483.22243, 1); // => 483.2
R.floor(8541, -1); // => 8540
R.floor(456789, -3); // => 456000
Data Last
R.floor(precision)(value);
R.floor(3)(123.9876); // => 123.987
R.floor(1)(483.22243); // => 483.2
R.floor(-1)(8541); // => 8540
R.floor(-3)(456789); // => 456000
Multiplies two numbers.
Data First
R.multiply(value, multiplicand);
R.multiply(3, 4); // => 12
R.reduce([1, 2, 3, 4], R.multiply, 1); // => 24
Data Last
R.multiply(multiplicand)(value);
R.multiply(4)(3); // => 12
R.map([1, 2, 3, 4], R.multiply(2)); // => [2, 4, 6, 8]
Compute the product of the numbers in the array, or return 1 for an empty array.
Data First
R.product(data);
R.product([1, 2, 3]); // => 6
R.product([]); // => 1
Data Last
R.product()(data);
R.pipe([1, 2, 3], R.product()); // => 6
R.pipe([], R.product()); // => 0
Rounds a given number to a specific precision.
If you'd like to round to an integer (i.e. use this function with constant precision === 0
),
use Math.round
instead, as it won't incur the additional library overhead.
Data First
R.round(value, precision);
R.round(123.9876, 3); // => 123.988
R.round(483.22243, 1); // => 483.2
R.round(8541, -1); // => 8540
R.round(456789, -3); // => 457000
Data Last
R.round(precision)(value);
R.round(3)(123.9876); // => 123.988
R.round(1)(483.22243); // => 483.2
R.round(-1)(8541); // => 8540
R.round(-3)(456789); // => 457000
Subtracts two numbers.
Data First
R.subtract(value, subtrahend);
R.subtract(10, 5); // => 5
R.subtract(10, -5); // => 15
R.reduce([1, 2, 3, 4], R.subtract, 20); // => 10
Data Last
R.subtract(subtrahend)(value);
R.subtract(5)(10); // => 5
R.subtract(-5)(10); // => 15
R.map([1, 2, 3, 4], R.subtract(1)); // => [0, 1, 2, 3]
Sums the numbers in the array, or return 0 for an empty array.
Data First
R.sum(data);
R.sum([1, 2, 3]); // => 6
R.sum([]); // => 0
Data Last
R.sum()(data);
R.pipe([1, 2, 3], R.sum()); // => 6
R.pipe([], R.sum()); // => 0
Add a new property to an object.
Data First
R.addProp(obj, prop, value);
R.addProp({ firstName: "john" }, "lastName", "doe"); // => {firstName: 'john', lastName: 'doe'}
Data Last
R.addProp(prop, value)(obj);
R.addProp("lastName", "doe")({ firstName: "john" }); // => {firstName: 'john', lastName: 'doe'}
Creates a deep copy of the value. Supported types: Array
, Object
, Number
, String
, Boolean
, Date
, RegExp
. Functions are assigned by reference rather than copied.
R.clone(value);
Returns an array of key/values of the enumerable properties of an object.
Data First
R.entries(object);
R.entries.strict(object);
R.entries({ a: 1, b: 2, c: 3 }); // => [['a', 1], ['b', 2], ['c', 3]]
R.entries.strict({ a: 1 } as const); // => [['a', 1]] typed Array<['a', 1]>
Data Last
R.entries()(object);
R.entries.strict()(object);
R.pipe({ a: 1, b: 2, c: 3 }, entries()); // => [['a', 1], ['b', 2], ['c', 3]]
R.pipe({ a: 1 } as const, entries.strict()); // => [['a', 1]] typed Array<['a', 1]>
Creates a new object by applying functions that is included in evolver
object parameter
to the data
object parameter according to their corresponding path.
Functions included in evolver
object will not be invoked
if its corresponding key does not exist in the data
object.
Also, values included in data
object will be kept as is
if its corresponding key does not exist in the evolver
object.
Data First
R.evolve(data, evolver);
const evolver = {
count: add(1),
time: { elapsed: add(1), remaining: add(-1) },
};
const data = {
id: 10,
count: 10,
time: { elapsed: 100, remaining: 1400 },
};
evolve(data, evolver);
// => {
// id: 10,
// count: 11,
// time: { elapsed: 101, remaining: 1399 },
// }
Data Last
R.evolve(evolver)(data);
const evolver = {
count: add(1),
time: { elapsed: add(1), remaining: add(-1) },
};
const data = {
id: 10,
count: 10,
time: { elapsed: 100, remaining: 1400 },
};
R.pipe(object, R.evolve(evolver));
// => {
// id: 10,
// count: 11,
// time: { elapsed: 101, remaining: 1399 },
// }
Iterate an object using a defined callback function. The original object is returned.
Data First
R.forEachObj(object, fn);
R.forEachObj({ a: 1 }, (val) => {
console.log(`${val}`);
}); // "1"
R.forEachObj.indexed({ a: 1 }, (val, key, obj) => {
console.log(`${key}: ${val}`);
}); // "a: 1"
Data Last
R.forEachObj(fn)(object);
R.pipe(
{ a: 1 },
R.forEachObj((val) => console.log(`${val}`)),
); // "1"
R.pipe(
{ a: 1 },
R.forEachObj.indexed((val, key) => console.log(`${key}: ${val}`)),
); // "a: 1"
Creates a new object from an array of tuples by pairing up first and second elements as {[key]: value}. If a tuple is not supplied for any element in the array, the element will be ignored If duplicate keys exist, the tuple with the greatest index in the input array will be preferred.
The strict option supports more sophisticated use-cases like those that would
result when calling the strict toPairs
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.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.fromEntries(tuples);
R.fromEntries.strict(tuples);
R.fromEntries([
["a", "b"],
["c", "d"],
]); // => {a: 'b', c: 'd'} (type: Record<string, string>)
R.fromEntries.strict(["a", 1] as const); // => {a: 1} (type: {a: 1})
Data Last
R.fromEntries()(tuples);
R.fromEntries.strict()(tuples);
R.pipe(
[
["a", "b"],
["c", "d"],
],
R.fromEntries(),
); // => {a: 'b', c: 'd'} (type: Record<string, string>)
R.pipe(["a", 1] as const, R.fromEntries.strict()); // => {a: 1} (type: {a: 1})
Creates an object that maps each key in data
to the result of mapper
for
that key. Duplicate keys are overwritten, guaranteeing that mapper
is run
for each item in data
.
There are several other functions that could be used to build an object from an array:
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.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.fromKeys(data, mapper);
R.fromKeys(["cat", "dog"], R.length()); // { cat: 3, dog: 3 } (typed as Partial<Record<"cat" | "dog", number>>)
R.fromKeys([1, 2], R.add(1)); // { 1: 2, 2: 3 } (typed as Partial<Record<1 | 2, number>>)
Data Last
R.fromKeys(mapper)(data);
R.pipe(["cat", "dog"], R.fromKeys(R.length())); // { cat: 3, dog: 3 } (typed as Partial<Record<"cat" | "dog", number>>)
R.pipe([1, 2], R.fromKeys(R.add(1))); // { 1: 2, 2: 3 } (typed as Partial<Record<1 | 2, number>>)
Returns an object whose keys and values are swapped. If the object contains duplicate values, subsequent values will overwrite previous values.
Data First
R.invert(object);
R.invert({ a: "d", b: "e", c: "f" }); // => { d: "a", e: "b", f: "c" }
Data Last
R.invert()(object);
R.pipe({ a: "d", b: "e", c: "f" }, R.invert()); // => { d: "a", e: "b", f: "c" }
Returns a new array containing the keys of the array or object.
Data First
R.keys(source);
R.keys.strict(source);
R.keys(["x", "y", "z"]); // => ['0', '1', '2']
R.keys({ a: "x", b: "y", c: "z" }); // => ['a', 'b', 'c']
R.keys.strict({ a: "x", b: "y", 5: "z" } as const); // => ['a', 'b', '5'], typed Array<'a' | 'b' | '5'>
R.pipe(["x", "y", "z"], R.keys); // => ['0', '1', '2']
R.pipe({ a: "x", b: "y", c: "z" }, R.keys); // => ['a', 'b', 'c']
R.pipe({ a: "x", b: "y", c: "z" }, R.keys, R.first()); // => 'a'
R.pipe({ a: "x", b: "y", 5: "z" } as const, R.keys.strict); // => ['a', 'b', '5'], typed Array<'a' | 'b' | '5'>
Maps keys of object
and keeps the same values.
Data First
R.mapKeys(object, fn);
R.mapKeys({ a: 1, b: 2 }, (key, value) => key + value); // => { a1: 1, b2: 2 }
Data Last
R.mapKeys(fn)(object);
R.pipe(
{ a: 1, b: 2 },
R.mapKeys((key, value) => key + value),
); // => { a1: 1, b2: 2 }
Maps values of object
and keeps the same keys.
Data First
R.mapValues(object, fn);
R.mapValues({ a: 1, b: 2 }, (value, key) => value + key); // => {a: '1a', b: '2b'}
Data Last
R.mapValues(fn)(object);
R.pipe(
{ a: 1, b: 2 },
R.mapValues((value, key) => value + key),
); // => {a: '1a', b: '2b'}
Merges two objects into one by combining their properties, effectively creating a new object that incorporates elements from both. The merge operation prioritizes the second object's properties, allowing them to overwrite those from the first object with the same names.
Equivalent to { ...data, ...source }
.
Data First
R.merge(data, source);
R.merge({ x: 1, y: 2 }, { y: 10, z: 2 }); // => { x: 1, y: 10, z: 2 }
Data Last
R.merge(source)(data);
R.pipe({ x: 1, y: 2 }, R.merge({ y: 10, z: 2 })); // => { x: 1, y: 10, z: 2 }
Merges the source
object into the destination
object. The merge is similar to performing { ...destination, ... source }
(where disjoint values from each object would be copied as-is, and for any overlapping props the value from source
would be used); But for each prop (p
), if both destination
and source
have a plain-object as a value, the value would be taken as the result of recursively deepMerging them (result.p === deepMerge(destination.p, source.p)
).
Data First
R.mergeDeep(destination, source);
R.mergeDeep({ foo: "bar", x: 1 }, { foo: "baz", y: 2 }); // => { foo: 'baz', x: 1, y: 2 }
Data Last
R.mergeDeep(source)(destination);
R.pipe({ foo: "bar", x: 1 }, R.mergeDeep({ foo: "baz", y: 2 })); // => { foo: 'baz', x: 1, y: 2 }
Creates an object containing a single key:value
pair.
R.objOf(value, key);
R.objOf(10, "a"); // => { a: 10 }
R.objOf(key)(value);
R.pipe(10, R.objOf("a")); // => { a: 10 }
Returns a partial copy of an object omitting the keys specified.
Data Last
R.omit(names)(obj);
R.pipe({ a: 1, b: 2, c: 3, d: 4 }, R.omit(["a", "d"])); // => { b: 2, c: 3 }
Data First
R.omit(obj, names);
R.omit({ a: 1, b: 2, c: 3, d: 4 }, ["a", "d"]); // => { b: 2, c: 3 }
Returns a partial copy of an object omitting the keys matching predicate.
Data First
R.omitBy(object, fn);
R.omitBy({ a: 1, b: 2, A: 3, B: 4 }, (val, key) => key.toUpperCase() === key); // => {a: 1, b: 2}
Data Last
R.omitBy(fn)(object);
R.omitBy((val, key) => key.toUpperCase() === key)({ a: 1, b: 2, A: 3, B: 4 }); // => {a: 1, b: 2}
Gets the value at path
of object
. If the resolved value is null
or undefined
, the defaultValue
is returned in its place.
Data First
R.pathOr(object, array, defaultValue);
R.pathOr({ x: 10 }, ["y"], 2); // 2
R.pathOr({ y: 10 }, ["y"], 2); // 10
Data Last
R.pathOr(array, defaultValue)(object);
R.pipe({ x: 10 }, R.pathOr(["y"], 2)); // 2
R.pipe({ y: 10 }, R.pathOr(["y"], 2)); // 10
Creates an object composed of the picked object
properties.
Data Last
R.pick([prop1, prop2])(object);
R.pipe({ a: 1, b: 2, c: 3, d: 4 }, R.pick(["a", "d"])); // => { a: 1, d: 4 }
Data First
R.pick(object, [prop1, prop2]);
R.pick({ a: 1, b: 2, c: 3, d: 4 }, ["a", "d"]); // => { a: 1, d: 4 }
Creates an object composed of the picked object
properties.
Data First
R.pickBy(object, fn);
R.pickBy({ a: 1, b: 2, A: 3, B: 4 }, (val, key) => key.toUpperCase() === key); // => {A: 3, B: 4}
Data Last
R.pickBy(fn)(object);
R.pickBy((val, key) => key.toUpperCase() === key)({ a: 1, b: 2, A: 3, B: 4 }); // => {A: 3, B: 4}
Gets the value of the given property.
Data Last
R.prop(prop)(object);
R.pipe({ foo: "bar" }, R.prop("foo")); // => 'bar'
Creates an object that maps the result of valueExtractor
with a key
resulting from running keyExtractor
on each item in data
. Duplicate keys
are overwritten, guaranteeing that the extractor functions are run on each
item in data
.
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.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.pullObject(data, keyExtractor, valueExtractor);
R.pullObject(
[
{ name: "john", email: "john@remedajs.com" },
{ name: "jane", email: "jane@remedajs.com" },
],
R.prop("name"),
R.prop("email"),
); // => { john: "john@remedajs.com", jane: "jane@remedajs.com" }
Data Last
R.pullObject(keyExtractor, valueExtractor)(data);
R.pipe(
[
{ name: "john", email: "john@remedajs.com" },
{ name: "jane", email: "jane@remedajs.com" },
],
R.pullObject(R.prop("email"), R.prop("name")),
); // => { john: "john@remedajs.com", jane: "jane@remedajs.com" }
Sets the value
at prop
of object
.
Data First
R.set(obj, prop, value);
R.set({ a: 1 }, "a", 2); // => { a: 2 }
Data Last
R.set(prop, value)(obj);
R.pipe({ a: 1 }, R.set("a", 2)); // => { a: 2 }
Sets the value at path
of object
.
Data First
R.setPath(obj, path, value);
R.setPath({ a: { b: 1 } }, ["a", "b"], 2); // => { a: { b: 2 } }
Data Last
R.setPath(path, value)(obj);
R.pipe({ a: { b: 1 } }, R.setPath(["a", "b"], 2)); // { a: { b: 2 } }
Swaps the positions of two properties in an object based on the provided keys.
Data First
swap(data, key1, key2);
swap({ a: 1, b: 2, c: 3 }, "a", "b"); // => {a: 2, b: 1, c: 3}
Data Last
swap(key1, key2)(data);
swap("a", "b")({ a: 1, b: 2, c: 3 }); // => {a: 2, b: 1, c: 3}
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}]
Returns a new array containing the values of the array or object.
Data First
R.values(source);
R.values(["x", "y", "z"]); // => ['x', 'y', 'z']
R.values({ a: "x", b: "y", c: "z" }); // => ['x', 'y', 'z']
R.pipe(["x", "y", "z"], R.values); // => ['x', 'y', 'z']
R.pipe({ a: "x", b: "y", c: "z" }, R.values); // => ['x', 'y', 'z']
R.pipe({ a: "x", b: "y", c: "z" }, R.values, R.first); // => 'x'
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']]
Combines two arrays.
Data First
R.concat(arr1, arr2);
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']
Excludes the values from other
array. The output maintains the same order
as the input. If either array
or other
contain multiple items with the
same values, all occurrences of those values will be removed. If the exact
number of copies should be observed (i.e. multi-set semantics), use
R.difference.multiset
instead. If the arrays don't contain duplicates, both
implementations yield the same result.
! DEPRECATED: Use R.difference.multiset(data, other)
(or R.filter(data, R.isNot(R.isIncludedIn(other)))
to keep the current runtime logic). R.difference.multiset
will replace R.difference
in v2!
Data First
R.difference(data, other);
R.difference.multiset(data, other);
R.difference([1, 2, 3, 4], [2, 5, 3]); // => [1, 4]
R.difference([1, 1, 2, 2], [1]); // => [2, 2]
R.difference.multiset([1, 1, 2, 2], [1]); // => [1, 2, 2]
Data First
R.difference(other)(data);
R.difference.multiset(other)(data);
R.pipe([1, 2, 3, 4], R.difference([2, 5, 3])); // => [1, 4]
R.pipe([1, 1, 2, 2], R.difference([1])); // => [2, 2]
R.pipe([1, 1, 2, 2], R.difference.multiset([1])); // => [1, 2, 2]
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]
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]
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]
Filter the elements of an array that meet the condition specified in a callback function.
Data First
R.filter(array, fn);
R.filter.indexed(array, fn);
R.filter([1, 2, 3], (x) => x % 2 === 1); // => [1, 3]
R.filter.indexed([1, 2, 3], (x, i, array) => x % 2 === 1); // => [1, 3]
Data Last
R.filter(fn)(array);
R.filter.indexed(fn)(array);
R.pipe(
[1, 2, 3],
R.filter((x) => x % 2 === 1),
); // => [1, 3]
R.pipe(
[1, 2, 3],
R.filter.indexed((x, i) => x % 2 === 1),
); // => [1, 3]
Returns the value of the first element in the array where predicate is true, and undefined otherwise.
Data First
R.find(items, fn);
R.find.indexed(items, fn);
R.find([1, 3, 4, 6], (n) => n % 2 === 0); // => 4
R.find.indexed([1, 3, 4, 6], (n, i) => n % 2 === 0); // => 4
Data Last
R.find(fn)(items);
R.find.indexed(fn)(items);
R.pipe(
[1, 3, 4, 6],
R.find((n) => n % 2 === 0),
); // => 4
R.pipe(
[1, 3, 4, 6],
R.find.indexed((n, i) => n % 2 === 0),
); // => 4
Returns the index of the first element in the array where predicate is true, and -1 otherwise.
Data First
R.findIndex(items, fn);
R.findIndex.indexed(items, fn);
R.findIndex([1, 3, 4, 6], (n) => n % 2 === 0); // => 2
R.findIndex.indexed([1, 3, 4, 6], (n, i) => n % 2 === 0); // => 2
Data Last
R.findIndex(fn)(items);
R.findIndex.indexed(fn)(items);
R.pipe(
[1, 3, 4, 6],
R.findIndex((n) => n % 2 === 0),
); // => 2
R.pipe(
[1, 3, 4, 6],
R.findIndex.indexed((n, i) => n % 2 === 0),
); // => 2
Returns the value of the last element in the array where predicate is true, and undefined otherwise.
Data First
R.findLast(items, fn);
R.findLast.indexed(items, fn);
R.findLast([1, 3, 4, 6], (n) => n % 2 === 1); // => 3
R.findLast.indexed([1, 3, 4, 6], (n, i) => n % 2 === 1); // => 3
Data Last
R.findLast(fn)(items);
R.findLast.indexed(fn)(items);
R.pipe(
[1, 3, 4, 6],
R.findLast((n) => n % 2 === 1),
); // => 3
R.pipe(
[1, 3, 4, 6],
R.findLast.indexed((n, i) => n % 2 === 1),
); // => 3
Returns the index of the last element in the array where predicate is true, and -1 otherwise.
Data First
R.findLastIndex(items, fn);
R.findLastIndex.indexed(items, fn);
R.findLastIndex([1, 3, 4, 6], (n) => n % 2 === 1); // => 1
R.findLastIndex.indexed([1, 3, 4, 6], (n, i) => n % 2 === 1); // => 1
Data Last
R.findLastIndex(fn)(items);
R.findLastIndex.indexed(fn)(items);
R.pipe(
[1, 3, 4, 6],
R.findLastIndex((n) => n % 2 === 1),
); // => 1
R.pipe(
[1, 3, 4, 6],
R.findLastIndex.indexed((n, i) => 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]
Map each element of an array using a defined callback function and flatten the mapped result.
Data First
R.flatMap(array, fn);
R.flatMap([1, 2, 3], (x) => [x, x * 10]); // => [1, 10, 2, 20, 3, 30]
Data Last
R.flatMap(fn)(array);
R.pipe(
[1, 2, 3],
R.flatMap((x) => [x, x * 10]),
); // => [1, 10, 2, 20, 3, 30]
Iterate an array using a defined callback function. The original array is returned instead of void
.
Data First
R.forEach(array, fn);
R.forEach.indexed(array, fn);
R.forEach([1, 2, 3], (x) => {
console.log(x);
}); // => [1, 2, 3]
R.forEach.indexed([1, 2, 3], (x, i) => {
console.log(x, i);
}); // => [1, 2, 3]
Data Last
R.forEach(fn)(array);
R.forEach.indexed(fn)(array);
R.pipe(
[1, 2, 3],
R.forEach((x) => {
console.log(x);
}),
); // => [1, 2, 3]
R.pipe(
[1, 2, 3],
R.forEach.indexed((x, i) => {
console.log(x, i);
}),
); // => [1, 2, 3]
Splits a collection into sets, grouped by the result of running each value through fn
.
Data First
R.groupBy(array, fn);
R.groupBy.strict(array, fn);
R.groupBy(["one", "two", "three"], (x) => x.length); // => {3: ['one', 'two'], 5: ['three']}
R.groupBy.strict([{ a: "cat" }, { a: "dog" }] as const, prop("a")); // => {cat: [{a: 'cat'}], dog: [{a: 'dog'}]} typed Partial<Record<'cat' | 'dog', NonEmptyArray<{a: 'cat' | 'dog'}>>>
R.groupBy([0, 1], (x) => (x % 2 === 0 ? "even" : undefined)); // => {even: [0]}
Data Last
R.groupBy(fn)(array);
R.pipe(
["one", "two", "three"],
R.groupBy((x) => x.length),
); // => {3: ['one', 'two'], 5: ['three']}
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 (casted to a string).
Use the strict version to maintain the given key's type, so long as it is a valid PropertyKey
.
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.strict(array, fn);
R.indexBy(["one", "two", "three"], (x) => x.length); // => {"3": 'two', "5": 'three'}
R.indexBy.strict(["one", "two", "three"], (x) => x.length); // => {3: 'two', 5: 'three'}
Data Last
R.indexBy(fn)(array);
R.indexBy.strict(fn)(array);
R.pipe(
["one", "two", "three"],
R.indexBy((x) => x.length),
); // => {"3": 'two', "5": 'three'}
R.pipe(
["one", "two", "three"],
R.indexBy.strict((x) => x.length),
); // => {3: 'two', 5: 'three'}
Returns a list of elements that exist in both array. The output maintains the
same order as the input. If either array
or other
contain multiple items
with the same values, all occurrences of those values will be present. If the
exact number of copies should be observed (i.e. multi-set semantics), use
R.intersection.multiset
instead. If the arrays don't contain duplicates,
both implementations yield the same result.
! DEPRECATED: Use R.intersection.multiset(data, other)
(or R.filter(data, R.isIncludedIn(other))
to keep the current runtime logic). R.intersection.multiset
will replace R.intersection
in v2!
Data First
R.intersection(data, other);
R.intersection.multiset(data, other);
R.intersection([1, 2, 3], [2, 3, 5]); // => [2, 3]
R.intersection([1, 1, 2, 2], [1]); // => [1, 1]
R.intersection.multiset([1, 1, 2, 2], [1]); // => [1]
Data First
R.intersection(other)(data);
R.intersection.multiset(other)(data);
R.pipe([1, 2, 3], R.intersection([2, 3, 5])); // => [2, 3]
R.pipe([1, 1, 2, 2], R.intersection([1])); // => [1, 1]
R.pipe([1, 1, 2, 2], R.intersection.multiset([1])); // => [1]
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
Map each element of an array using a defined callback function. If the input
array is a tuple use the strict
variant to maintain it's shape.
Data First
R.map(array, fn);
R.map.indexed(array, fn);
R.map.strict(array, fn);
R.map.strict.indexed(array, fn);
R.map([1, 2, 3], (x) => x * 2); // => [2, 4, 6], typed number[]
R.map.indexed([0, 0, 0], (x, i) => i); // => [0, 1, 2], typed number[]
R.map.strict([0, 0] as const, (x) => x + 1); // => [1, 1], typed [number, number]
R.map.strict.indexed([0, 0] as const, (x, i) => x + i); // => [0, 1], typed [number, number]
Data Last
R.map(fn)(array);
R.map.indexed(fn)(array);
R.pipe(
[0, 1, 2],
R.map((x) => x * 2),
); // => [0, 2, 4]
R.pipe(
[0, 0, 0],
R.map.indexed((x, i) => i),
); // => [0, 1, 2]
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.indexed(array, fn);
R.mapToObj([1, 2, 3], (x) => [String(x), x * 2]); // => {1: 2, 2: 4, 3: 6}
R.mapToObj.indexed([0, 0, 0], (x, i) => [i, i]); // => {0: 0, 1: 1, 2: 2}
Data Last
R.mapToObj(fn)(array);
R.mapToObj.indexed(fn)(array);
R.pipe(
[1, 2, 3],
R.mapToObj((x) => [String(x), x * 2]),
); // => {1: 2, 2: 4, 3: 6}
R.pipe(
[0, 0, 0],
R.mapToObj.indexed((x, i) => [i, i]),
); // => {0: 0, 1: 1, 2: 2}
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(items, fn, initialValue);
R.mapWithFeedback.indexed(items, fn, initialValue);
R.mapWithFeedback([1, 2, 3, 4, 5], (prev, x) => prev + x, 100); // => [101, 103, 106, 110, 115]
R.mapWithFeedback.indexed(
[1, 2, 3, 4, 5],
(prev, x, i, array) => prev + x,
100,
); // => [101, 103, 106, 110, 115]
Data Last
R.mapWithFeedback(fn, initialValue)(array);
R.pipe(
[1, 2, 3, 4, 5],
R.mapWithFeedback((prev, x) => prev + x, 100),
); // => [101, 103, 106, 110, 115]
R.pipe(
[1, 2, 3, 4, 5],
R.mapWithFeedback.indexed((prev, x, i, array) => 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.meanBy.indexed(fn)(array);
R.pipe(
[{ a: 5 }, { a: 1 }, { a: 3 }],
R.meanBy((x) => x.a),
); // 3
Data First
R.meanBy(array, fn);
R.meanBy.indexed(array, fn);
R.meanBy([{ a: 5 }, { a: 1 }, { a: 3 }], (x) => x.a); // 3
Merges a list of objects into a single object.
R.mergeAll(objects);
R.mergeAll([{ a: 1, b: 1 }, { b: 2, c: 3 }, { d: 10 }]); // => { a: 1, b: 2, c: 3, d: 10 }
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(array, fn);
R.partition(["one", "two", "forty two"], (x) => x.length === 3); // => [['one', 'two'], ['forty two']]
Data First
R.partition(array, fn);
R.partition(["one", "two", "forty two"], (x) => x.length === 3); // => [['one', 'two'], ['forty two']]
Data Last
R.partition(fn)(array);
R.pipe(
["one", "two", "forty two"],
R.partition((x) => x.length === 3),
); // => [['one', 'two'], ['forty two']]
Data Last
R.partition(fn)(array);
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 First
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
Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
Data First
R.reduce(items, fn, initialValue);
R.reduce.indexed(items, fn, initialValue);
R.reduce([1, 2, 3, 4, 5], (acc, x) => acc + x, 100); // => 115
R.reduce.indexed([1, 2, 3, 4, 5], (acc, x, i, array) => 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
R.pipe(
[1, 2, 3, 4, 5],
R.reduce.indexed((acc, x, i, array) => 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. It's not guaranteed to be stable.
If the input array is more complex (non-empty array, tuple, etc...) use the strict mode to maintain its shape.
Data First
R.sort(items, cmp);
R.sort.strict(items, cmp);
R.sort([4, 2, 7, 5], (a, b) => a - b); // => [2, 4, 5, 7] typed Array<number>
R.sort.strict([4, 2] as [number, number], (a, b) => a - b); // [2, 4] typed [number, number]
Data Last
R.sort(cmp)(items);
R.sort.strict(cmp)(items);
R.pipe(
[4, 2, 7, 5],
R.sort((a, b) => a - b),
); // => [2, 4, 5, 7] typed Array<number>
R.pipe(
[4, 2] as [number, number],
R.sort.strict((a, b) => a - b),
); // => [2, 4] typed [number, number]
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.
To maintain the shape of more complex inputs (like non-empty arrays, tuples, etc...) use the strict
variant.
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.sortBy.strict(...rules)(data);
R.pipe(
[{ a: 1 }, { a: 3 }, { a: 7 }, { a: 2 }],
R.sortBy((x) => x.a),
); // => [{ a: 1 }, { a: 2 }, { a: 3 }, { a: 7 }] typed Array<{a:number}>
R.pipe(
[{ a: 1 }, { a: 3 }] as const,
R.sortBy.strict((x) => x.a),
); // => [{ a: 1 }, { a: 3 }] typed [{a: 1 | 3}, {a: 1 | 3}]
Data First
R.sortBy(data, ...rules);
R.sortBy.strict(data, ...rules);
R.sortBy([{ a: 1 }, { a: 3 }, { a: 7 }, { a: 2 }], (x) => x.a);
// => [{ a: 1 }, { a: 2 }, { a: 3 }, { a: 7 }] typed Array<{a:number}>
R.sortBy(
[
{ color: "red", weight: 2 },
{ color: "blue", weight: 3 },
{ color: "green", weight: 1 },
{ color: "purple", weight: 1 },
],
[(x) => x.weight, "asc"],
(x) => x.color,
);
// =>
// {color: 'green', weight: 1},
// {color: 'purple', weight: 1},
// {color: 'red', weight: 2},
// {color: 'blue', weight: 3},
// typed Array<{color: string, weight: number}>
R.sortBy.strict([{ a: 1 }, { a: 3 }] as const, (x) => x.a);
// => [{ a: 1 }, { a: 3 }] typed [{a: 1 | 3}, {a: 1 | 3}]
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
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.
Data First
R.sortedIndexBy(data, item, valueFunction);
R.sortedIndexBy([{ age: 20 }, { age: 22 }], { age: 21 }, prop("age")); // => 1
Data Last
R.sortedIndexBy(data, item, valueFunction);
R.sortedIndexBy([{ age: 20 }, { age: 22 }], { age: 21 }, prop("age")); // => 1
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:
- It would run at O(logN) time instead of O(N) time.
- It always returns a value (it would return
data.length
if the predicate returnstrue
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.
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
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
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.
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 predicate.
Data Last
R.sumBy(fn)(array);
R.sumBy.indexed(fn)(array);
R.pipe(
[{ a: 5 }, { a: 1 }, { a: 3 }],
R.sumBy((x) => x.a),
); // 9
Data First
R.sumBy(array, fn);
R.sumBy.indexed(array, fn);
R.sumBy([{ a: 5 }, { a: 1 }, { a: 3 }], (x) => x.a); // 9
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); // => ['c', 'b', 'a']
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]
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']
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(array, fn);
R.takeWhile([1, 2, 3, 4, 3, 2, 1], (x) => x !== 4); // => [1, 2, 3]
Data Last
R.takeWhile(fn)(array);
R.pipe(
[1, 2, 3, 4, 3, 2, 1],
R.takeWhile((x) => x !== 4),
); // => [1, 2, 3]
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]
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(array, fn);
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(fn)(array);
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}]
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.
If the input array are tuples, you can use the strict option to get another tuple instead of a generic array type.
Data First
R.zip(first, second);
R.zip([1, 2], ["a", "b"]); // => [[1, 'a'], [2, 'b']] (type: [number, string][])
R.zip.strict([1, 2] as const, ["a", "b"] as const); // => [[1, 'a'], [2, 'b']] (type: [[1, 'a'], [2, 'b']])
Data Last
R.zip(second)(first);
R.zip(["a", "b"])([1, 2]); // => [[1, 'a'], [2, 'b']] (type: [number, string][])
R.zip.strict(["a", "b"] as const)([1, 2] as const); // => [[1, 'a'], [2, 'b']] (type: [[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.
Data First
R.zipWith(first, second, fn);
R.zipWith(["1", "2", "3"], ["a", "b", "c"], (a, b) => a + b); // => ['1a', '2b', '3c']
Data Last
R.zipWith(fn)(first, second);
R.zipWith((a, b) => a + b)(["1", "2", "3"], ["a", "b", "c"]); // => ['1a', '2b', '3c']
Data Last
R.zipWith(fn)(first, second);
R.zipWith((a, b) => a + b, ["a", "b", "c"])(["1", "2", "3"]); // => ['1a', '2b', '3c']
Filter out all falsy values. The values false
, null
, 0
, ""
,
undefined
, and NaN
are falsy.
! DEPRECATED: Use R.filter(items, R.isTruthy)
. Will be removed in V2!
R.compact(array);
R.compact([0, 1, false, 2, "", 3]); // => [1, 2, 3]
Counts how many values of the collection pass the specified predicate.
! DEPRECATED: Use R.filter(items, fn).length
. Will be removed in v2!
Data First
R.countBy(array, fn);
R.countBy([1, 2, 3, 4, 5], (x) => x % 2 === 0); // => 2
Data Last
R.countBy(fn)(array);
R.pipe(
[1, 2, 3, 4, 5],
R.countBy((x) => x % 2 === 0),
); // => 2
Creates a data-last pipe function. First function must be always annotated. Other functions are automatically inferred.
! DEPRECATED: Use R.piped(op1, op2, op3)
. Will be removed in V2!
R.createPipe(op1, op2, op3)(data);
R.createPipe(
(x: number) => x * 2,
(x) => x * 3,
)(1); // => 6
Returns true if its arguments are equivalent, false otherwise. NOTE: Doesn't handle cyclical data structures.
! DEPRECATED: Use R.isDeepEqual(a, b)
. Will be removed in V2.
Data First
R.equals(a, b);
R.equals(1, 1); //=> true
R.equals(1, "1"); //=> false
R.equals([1, 2, 3], [1, 2, 3]); //=> true
Data Last
R.equals(b)(a);
R.equals(1)(1); //=> true
R.equals("1")(1); //=> false
R.equals([1, 2, 3])([1, 2, 3]); //=> true
Map each element of an array into an object using a defined callback function and flatten the result.
! DEPRECATED: Use R.fromEntries.strict(R.flatMap(array, fn))
. Will be removed in V2!
Data First
R.flatMapToObj(array, fn);
R.flatMapToObj.indexed(array, fn);
R.flatMapToObj([1, 2, 3], (x) => (x % 2 === 1 ? [[String(x), x]] : [])); // => {1: 1, 3: 3}
R.flatMapToObj.indexed(["a", "b"], (x, i) => [
[x, i],
[x + x, i + i],
]); // => {a: 0, aa: 0, b: 1, bb: 2}
Data Last
R.flatMapToObj(fn)(array);
R.flatMapToObj(fn)(array);
R.pipe(
[1, 2, 3],
R.flatMapToObj((x) => (x % 2 === 1 ? [[String(x), x]] : [])),
); // => {1: 1, 3: 3}
R.pipe(
["a", "b"],
R.flatMapToObj.indexed((x, i) => [
[x, i],
[x + x, i + i],
]),
); // => {a: 0, aa: 0, b: 1, bb: 2}
Flattens array
a single level deep.
! DEPRECATED Use R.flat(data)
. Will be removed in V2!
Data First
R.flatten(array);
R.flatten([[1, 2], [3], [4, 5]]); // => [1, 2, 3, 4, 5]
Data Last
R.flatten()(array);
R.pipe([[1, 2], [3], [4, 5]], R.flatten()); // => [1, 2, 3, 4, 5]
Recursively flattens array
.
! DEPRECATED Use R.flat(data, 4)
. The typing for flattenDeep
was broken for arrays nested more than 4 levels deep; this might lead to typing issues when migrating to the new function. Will be removed in V2!
R.flattenDeep(array);
R.flattenDeep([
[1, 2],
[[3], [4, 5]],
]); // => [1, 2, 3, 4, 5]
Data Last
R.flattenDeep()(array);
R.pipe(
[
[1, 2],
[[3], [4, 5]],
],
R.flattenDeep(),
); // => [1, 2, 3, 4, 5]
Creates a new object from an array of tuples by pairing up first and second elements as {[key]: value}. If a tuple is not supplied for any element in the array, the element will be ignored If duplicate keys exist, the tuple with the greatest index in the input array will be preferred.
The strict option supports more sophisticated use-cases like those that would
result when calling the strict toPairs
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.mapToObj
- Builds an object from an array of items and a single mapper for key-value pairs. Refer to the docs for more details.
! DEPRECATED: Use R.fromEntries(pairs)
, for dataLast invocations use the functional form R.fromEntries()
. Will be removed in V2!
Data First
R.fromPairs(tuples);
R.fromPairs.strict(tuples);
R.fromPairs([
["a", "b"],
["c", "d"],
]); // => {a: 'b', c: 'd'} (type: Record<string, string>)
R.fromPairs.strict(["a", 1] as const); // => {a: 1} (type: {a: 1})
R.pipe(
[
["a", "b"],
["c", "d"],
],
R.fromPairs,
); // => {a: 'b', c: 'd'} (type: Record<string, string>)
R.pipe(["a", 1] as const, R.fromPairs.strict); // => {a: 1} (type: {a: 1})
A function that checks if the passed parameter is Nil (null or undefined) and narrows its type accordingly.
! DEPRECATED: Use R.isNullish(data)
. Will be removed in V2!
R.isNil(data);
R.isNil(undefined); //=> true
R.isNil(null); //=> true
R.isNil("somethingElse"); //=> false
A function that checks if the passed parameter is of type Object and narrows its type accordingly.
! DEPRECATED: Use: R.isObjectType(data) && R.isNonNull(data) && !R.isArray(data)
or R.isPlainObject(data)
. Will be removed in V2!
R.isObject(data);
R.isObject({}); //=> true
R.isObject(Promise.resolve("something")); //=> true
R.isObject(new Date()); //=> true
R.isObject(new Error("error")); //=> true
R.isObject("somethingElse"); //=> false
Returns the max element using the provided predicate.
! DEPRECATED: Use R.firstBy([fn, "desc"])
. Will be removed in V2!
Data Last
R.maxBy(fn)(array);
R.maxBy.indexed(fn)(array);
R.pipe(
[{ a: 5 }, { a: 1 }, { a: 3 }],
R.maxBy((x) => x.a),
); // { a: 5 }
Data First
R.maxBy(array, fn);
R.maxBy.indexed(array, fn);
R.maxBy([{ a: 5 }, { a: 1 }, { a: 3 }], (x) => x.a); // { a: 5 }
Returns the min element using the provided predicate.
! DEPRECATED: Use R.firstBy(fn)
. Will be removed in V2!
Data Last
R.minBy(fn)(array);
R.minBy.indexed(fn)(array);
R.pipe(
[{ a: 5 }, { a: 1 }, { a: 3 }],
R.minBy((x) => x.a),
); // { a: 1 }
Data First
R.minBy(array, fn);
R.minBy.indexed(array, fn);
R.minBy([{ a: 5 }, { a: 1 }, { a: 3 }], (x) => x.a); // { a: 1 }
A function that returns always undefined
.
! DEPRECATED: Use R.constant(undefined)
, or R.doNothing()
if the function doesn't need to return a value. Will be removed in V2!
R.noop();
onSomething(R.noop);
Reject the elements of an array that meet the condition specified in a callback function.
! DEPRECATED: Use R.filter(items, R.isNot(fn))
. Will be removed in V2!
Data First
R.reject(array, fn);
R.reject.indexed(array, fn);
R.reject([1, 2, 3], (x) => x % 2 === 0); // => [1, 3]
R.reject.indexed([1, 2, 3], (x, i, array) => x % 2 === 0); // => [1, 3]
Data First
R.reject(array, fn);
R.reject.indexed(array, fn);
R.reject([1, 2, 3], (x) => x % 2 === 0); // => [1, 3]
R.reject.indexed([1, 2, 3], (x, i, array) => x % 2 === 0); // => [1, 3]
Returns an array of key/values of the enumerable properties of an object.
! DEPRECATED Use R.entries(object)
, for dataLast invocations use the functional form R.entries()
. Will be removed in V2!
Data First
R.toPairs(object);
R.toPairs.strict(object);
R.toPairs({ a: 1, b: 2, c: 3 }); // => [['a', 1], ['b', 2], ['c', 3]]
R.toPairs.strict({ a: 1 } as const); // => [['a', 1]] typed Array<['a', 1]>
R.pipe({ a: 1, b: 2, c: 3 }, toPairs); // => [['a', 1], ['b', 2], ['c', 3]]
R.pipe({ a: 1 } as const, toPairs.strict); // => [['a', 1]] typed Array<['a', 1]>
Gives a single-word string description of the (native) type of a value, returning such answers as 'Object', 'Number', 'Array', or 'Null'. Does not attempt to distinguish user Object types any further, reporting them all as 'Object'.
! DEPRECATED: Use typeof val
, or one of the guards offered by this library. Will be removed in V2! We don't know what the use case for this function is. If you have a use case reach out via a GitHub issue so we can discuss this.
R.type(obj);
R.type({}); //=> "Object"
R.type(1); //=> "Number"
R.type(false); //=> "Boolean"
R.type("s"); //=> "String"
R.type(null); //=> "Null"
R.type([]); //=> "Array"
R.type(/[A-z]/); //=> "RegExp"
R.type(() => {}); //=> "Function"
R.type(undefined); //=> "Undefined"
Returns a new array containing only one copy of each element in the original list. Elements are compared by reference using Set.
! DEPRECATED: Use R.unique(array)
. Will be removed in V2.
Data First
R.uniq(array);
R.uniq([1, 2, 2, 5, 1, 6, 7]); // => [1, 2, 5, 6, 7]
Data Last
R.uniq()(array);
R.pipe(
[1, 2, 2, 5, 1, 6, 7], // only 4 iterations
R.uniq(),
R.take(3),
); // => [1, 2, 5]
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.
! DEPRECATED: Use R.uniqueBy(array, fn)
. Will be removed in V2!
Data First
R.uniqBy(array, fn);
R.uniqBy(
[{ 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.uniqBy(fn)(array);
R.pipe(
[{ n: 1 }, { n: 2 }, { n: 2 }, { n: 5 }, { n: 1 }, { n: 6 }, { n: 7 }], // only 4 iterations
R.uniqBy((obj) => obj.n),
R.take(3),
); // => [{n: 1}, {n: 2}, {n: 5}]
Returns a new array containing only one copy of each element in the original list. Elements are compared by custom comparator isEquals.
! DEPRECATED: Use R.uniqueWith(array, isEquals)
. Will be removed in V2!
Data First
R.uniqWith(array, isEquals);
R.uniqWith(
[{ 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.uniqWith(isEquals)(array);
R.uniqWith(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.uniqWith(R.equals),
R.take(3),
); // => [{a: 1}, {a: 2}, {a: 5}]
Creates a new object from two supplied lists by pairing up equally-positioned items. Key/value pairing is truncated to the length of the shorter of the two lists.
! DEPRECATED: Use R.fromEntries.strict(R.zip(first, second))
. Will be removed in V2!
Data First
R.zipObj(first, second);
R.zipObj(["a", "b"], [1, 2]); // => {a: 1, b: 2}
Data Last
R.zipObj(second)(first);
R.zipObj([1, 2])(["a", "b"]); // => {a: 1, b: 2}
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.
!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'
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.
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]
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.
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
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.
Data Last
R.doNothing();
myApi({ onSuccess: handleSuccess, onError: R.doNothing() });
myApi({ onSuccess: isDemoMode ? R.doNothing() : handleSuccess });
A function that always returns the param passed to it.
R.identity(data);
R.identity("foo"); // => 'foo'
Creates a function that is restricted to invoking func
once. Repeat calls to the function return the value of the first invocation.
R.once(fn);
const initialize = R.once(createApplication);
initialize();
initialize();
// => `createApplication` is invoked once
Perform left-to-right function composition.
Data First
R.pipe(data, op1, op2, op3);
R.pipe(
[1, 2, 3, 4],
R.map((x) => x * 2),
(arr) => [arr[0] + arr[1], arr[2] + arr[3]],
); // => [6, 14]
A dataLast version of pipe
that could be used to provide more complex
computations to functions that accept a function as a param (like map
,
filter
, groupBy
, etc.).
The first function must be always annotated. Other functions are automatically inferred.
R.piped(...ops)(data);
R.filter(
[{ a: 1 }, { a: 2 }, { a: 3 }],
R.piped(R.prop("a"), (x) => x % 2 === 0),
); // => [{ a: 2 }]
Creates a function with dataFirst
and dataLast
signatures.
purry
is a dynamic function and it's not type safe. It should be wrapped by
a function that have proper typings. Refer to the example below for correct
usage.
!IMPORTANT: functions that simply call purry
and return the result (like
almost all functions in this library) should return unknown
themselves if
an explicit return type is required. This is because we currently don't
provide a generic return type that is built from the input function, and
crafting one manually isn't worthwhile as we rely on function declaration
overloading to combine the types for dataFirst and dataLast invocations!
R.purry(fn, arguments);
function _findIndex(array, fn) {
for (let i = 0; i < array.length; i++) {
if (fn(array[i])) {
return i;
}
}
return -1;
}
// data-first
function findIndex<T>(array: T[], fn: (item: T) => boolean): number;
// data-last
function findIndex<T>(fn: (item: T) => boolean): (array: T[]) => number;
function findIndex() {
return R.purry(_findIndex, arguments);
}
Checks if subObject
is a sub-object of object
, which means for every
property and value in subObject
, there's the same property in object
with an equal value. Equality is checked with isDeepEqual
.
Data First
R.hasSubObject(data, subObject);
R.hasSubObject({ a: 1, b: 2, c: 3 }, { a: 1, c: 3 }); //=> true
R.hasSubObject({ a: 1, b: 2, c: 3 }, { b: 4 }); //=> false
R.hasSubObject({ a: 1, b: 2, c: 3 }, {}); //=> true
Data Last
R.hasSubObject(subObject)(data);
R.hasSubObject({ a: 1, c: 3 })({ a: 1, b: 2, c: 3 }); //=> true
R.hasSubObject({ b: 4 })({ a: 1, b: 2, c: 3 }); //=> false
R.hasSubObject({})({ a: 1, b: 2, c: 3 }); //=> true
A function that checks if the passed parameter is an Array and narrows its type accordingly.
R.isArray(data);
R.isArray([5]); //=> true
R.isArray([]); //=> true
R.isArray("somethingElse"); //=> false
A function that checks if the passed parameter is a boolean and narrows its type accordingly.
R.isBoolean(data);
R.isBoolean(true); //=> true
R.isBoolean(false); //=> true
R.isBoolean("somethingElse"); //=> false
A function that checks if the passed parameter is a Date and narrows its type accordingly.
R.isDate(data);
R.isDate(new Date()); //=> true
R.isDate("somethingElse"); //=> false
Performs a deep semantic comparison between two values to determine if they
are equivalent. For primitive values this is equivalent to ===
, for arrays
the check would be performed on every item recursively, in order, and for
objects all props will be compared recursively. The built-in Date and RegExp
are special-cased and will be compared by their values.
!IMPORTANT: TypedArrays and symbol properties of objects are not supported right now and might result in unexpected behavior. Please open an issue in the Remeda github project if you need support for these types.
The result would be narrowed to the second value so that the function can be used as a type guard.
Data First
R.isDeepEqual(data, other);
R.isDeepEqual(1, 1); //=> true
R.isDeepEqual(1, "1"); //=> false
R.isDeepEqual([1, 2, 3], [1, 2, 3]); //=> true
Data Last
R.isDeepEqual(other)(data);
R.pipe(1, R.isDeepEqual(1)); //=> true
R.pipe(1, R.isDeepEqual("1")); //=> false
R.pipe([1, 2, 3], R.isDeepEqual([1, 2, 3])); //=> true
A function that checks if the passed parameter is defined and narrows its
type accordingly. To test specifically for undefined
(and not null
) use
the strict variant of this function.
! DEPRECATED: If your type accepts null
use R.isNullish(data)
, otherwise prefer R.isDefined.strict(data)
. The non-strict version will be removed in V2!
R.isDefined(data);
R.isDefined.strict(data);
R.isDefined("string"); //=> true
R.isDefined(null); //=> false
R.isDefined(undefined); //=> false
R.isDefined.strict(null); //=> true
R.isDefined.strict(undefined); //=> false
A function that checks if the passed parameter is empty.
undefined
is also considered empty, but only when it's in a union with a
string
or string-like type.
This guard doesn't work negated because of typescript limitations! If you
need to check that an array is not empty, use R.hasAtLeast(data, 1)
and not !R.isEmpty(data)
. For strings and objects there's no way in
typescript to narrow the result to a non-empty type.
R.isEmpty(data);
R.isEmpty(undefined); //=>true
R.isEmpty(""); //=> true
R.isEmpty([]); //=> true
R.isEmpty({}); //=> true
R.isEmpty("test"); //=> false
R.isEmpty([1, 2, 3]); //=> false
R.isEmpty({ length: 0 }); //=> false
A function that checks if the passed parameter is an Error and narrows its type accordingly.
R.isError(data);
R.isError(new Error("message")); //=> true
R.isError("somethingElse"); //=> false
A function that checks if the passed parameter is a Function and narrows its type accordingly.
R.isFunction(data);
R.isFunction(() => {}); //=> true
R.isFunction("somethingElse"); //=> false
Checks if the item is included in the container. This is a wrapper around
Array.prototype.includes
and Set.prototype.has
and thus relies on the
same equality checks that those functions do (which is reference equality,
e.g. ===
). In some cases the input's type is also narrowed to the
container's item types.
Notice that unlike most functions, this function takes a generic item as it's data and an array as it's parameter.
Data First
R.isIncludedIn(data, container);
R.isIncludedIn(2, [1, 2, 3]); // => true
R.isIncludedIn(4, [1, 2, 3]); // => false
const data = "cat" as "cat" | "dog" | "mouse";
R.isIncludedIn(data, ["cat", "dog"] as const); // true (typed "cat" | "dog");
Data Last
R.isIncludedIn(container)(data);
R.pipe(2, R.isIncludedIn([1, 2, 3])); // => true
R.pipe(4, R.isIncludedIn([1, 2, 3])); // => false
const data = "cat" as "cat" | "dog" | "mouse";
R.pipe(data, R.isIncludedIn(["cat", "dog"] as const)); // => true (typed "cat" | "dog");
A function that checks if the passed parameter is not null
and narrows its type accordingly.
Notice that undefined
is not null!
R.isNonNull(data);
R.isNonNull("string"); //=> true
R.isNonNull(null); //=> false
R.isNonNull(undefined); //=> true
A function that checks if the passed parameter is defined AND isn't null
and narrows its type accordingly.
R.isNonNullish(data);
R.isNonNullish("string"); //=> true
R.isNonNullish(null); //=> false
R.isNonNullish(undefined); //=> false
A function that takes a guard function as predicate and returns a guard that negates it.
Data Last
R.isNot(R.isTruthy)(data);
R.isNot(R.isTruthy)(false); //=> true
R.isNot(R.isTruthy)(true); //=> false
A function that checks if the passed parameter is either null
or
undefined
and narrows its type accordingly.
R.isNullish(data);
R.isNullish(undefined); //=> true
R.isNullish(null); //=> true
R.isNullish("somethingElse"); //=> false
A function that checks if the passed parameter is a number and narrows its type accordingly.
R.isNumber(data);
R.isNumber(1); //=> true
R.isNumber("notANumber"); //=> false
Checks if the given parameter is of type "object"
via typeof
, excluding null
.
It's important to note that in JavaScript, many entities are considered objects, like Arrays, Classes, RegExps, Maps, Sets, Dates, URLs, Promise, Errors, and more. Although technically an object too, null
is not considered an object by this function, so that its easier to narrow nullables.
For a more specific check that is limited to plain objects (simple struct/shape/record-like objects), consider using isPlainObject
instead. For a simpler check that only removes null
from the type prefer isNonNull
or isDefined
.
Data First
R.isObjectType(data);
// true
R.isObjectType({}); //=> true
R.isObjectType([]); //=> true
R.isObjectType(Promise.resolve("something")); //=> true
R.isObjectType(new Date()); //=> true
R.isObjectType(new Error("error")); //=> true
// false
R.isObjectType("somethingElse"); //=> false
R.isObjectType(null); //=> false
Checks if data
is a "plain" object. A plain object is defined as an object with string keys and values of any type, including primitives, other objects, functions, classes, etc (aka struct/shape/record/simple). Technically, a plain object is one whose prototype is either Object.prototype
or null
, ensuring it does not inherit properties or methods from other object types.
This function is narrower in scope than isObjectType
, which accepts any entity considered an "object"
by JavaScript's typeof
.
Note that Maps, Arrays, and Sets are not considered plain objects and would return false
.
R.isPlainObject(data);
// true
R.isPlainObject({}); //=> true
R.isPlainObject({ a: 123 }); //=> true
// false
R.isPlainObject([]); //=> false
R.isPlainObject(Promise.resolve("something")); //=> false
R.isPlainObject(new Date()); //=> false
R.isPlainObject(new Error("error")); //=> false
R.isPlainObject("somethingElse"); //=> false
R.isPlainObject(null); //=> false
A function that checks if the passed parameter is a Promise and narrows its type accordingly.
R.isPromise(data);
R.isPromise(Promise.resolve(5)); //=> true
R.isPromise(Promise.reject(5)); //=> true
R.isPromise("somethingElse"); //=> false
A function that checks if the passed parameter is a string and narrows its type accordingly.
R.isString(data);
R.isString("string"); //=> true
R.isString(1); //=> false
A function that checks if the passed parameter is a symbol and narrows its type accordingly.
R.isSymbol(data);
R.isSymbol(Symbol("foo")); //=> true
R.isSymbol(1); //=> false
A function that checks if the passed parameter is truthy and narrows its type accordingly.
R.isTruthy(data);
R.isTruthy("somethingElse"); //=> true
R.isTruthy(null); //=> false
R.isTruthy(undefined); //=> false
R.isTruthy(false); //=> false
R.isTruthy(0); //=> false
R.isTruthy(""); //=> false
Random a non-cryptographic random string from characters a-zA-Z0-9.
Data First
R.randomString(length);
R.randomString(5); // => aB92J
R.pipe(5, R.randomString); // => aB92J
A data-last version of String.prototype.slice
so it could be used in pipes.
NOTE: You don't need this function if you are calling it directly, just use
String.prototype.slice
directly. This function doesn't provide any type
improvements over the built-in types.
Data Last
R.sliceString(indexStart)(string);
R.sliceString(indexStart, indexEnd)(string);
R.sliceString(1)(`abcdefghijkl`); // => `bcdefghijkl`
R.sliceString(4, 7)(`abcdefghijkl`); // => `efg`
Converts a path string to an array of string keys (including array index access keys).
!IMPORTANT!: Attempting to pass a simple string
type will result in the result being inferred
as never
. This is intentional to help with type-safety as this function is primarily intended
to help with other "object path access" functions like pathOr
or setPath
.
Data First
R.stringToPathArray(path);
Calls the given function with the given value, then returns the given value. The return value of the provided function is ignored.
This allows "tapping into" a function sequence in a pipe, to perform side effects on intermediate results.
Data First
R.tap(value, fn);
R.tap("foo", console.log); // => "foo"
Data Last
R.tap(fn)(value);
R.pipe(
[-5, -1, 2, 3],
R.filter((n) => n > 0),
R.tap(console.log), // prints [2, 3]
R.map((n) => n * 2),
); // => [4, 6]
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
.