π(π) = π, A set of useful functions built on top of Ramda that are not in the core.
Function are defined in a readme for now.
If you are looking for more advanced set of extensions look at ramda-adjunct
String β {s: a} β a
Just like lodash get
accepts .
delimeted path instead of an array:
const pathGetter = R.compose(R.path, R.split('.'))
const get = R.curry((path, obj) => pathGetter(path)(obj))
usage:
get('a.b', {a: {b: 8}}) //8
String β a β {a} β {a}
Sets a property on an object using given path, returns new object.
const pathSetter = R.compose(R.assocPath, R.split('.'))
const set = R.curry((path, value, obj) => pathSetter(path)(value, obj))
usage:
set('a.b.c', 8, {}) // {a: {b: {c: 8}}}
Obj β Boolean
Checks if value is nil or empty.
const isNilOrEmpty = R.either(R.isNil, R.isEmpty)
Same as differenceWith, but for multiple lists
const differenceAllWith = R.curry((predicate, array) =>
R.reduce(
R.differenceWith(predicate),
R.head(array),
R.tail(array)
))
Replaces all occurences of a string with given replacement string.
const strReplaceAll = R.curry((search, replacement, str) =>
R.replace(new RegExp(search, 'g'), replacement, str),
)
usage:
R.pipe(
strReplaceAll('&', 'ramda'),
strReplaceAll('x', 'is'),
strReplaceAll('y', 'cool'),
)('& x y')
// outputs "ramda is cool"
((originalItem, itemToReplaceWith) β Boolean) β Array β Array β Array
Replaces original items with given array of items using predicate, if predicate returns true, item will be replaced in original items in-place (it's orignal index) with the item from "replaceWithItems".
const replaceBy = R.curry((predicate, replaceWithItems, originalItems) =>
R.compose(
R.reduce(
(acc, itemsMap) =>
R.update(itemsMap.index, itemsMap.item, acc),
originalItems
),
R.map(replacementItem => ({
item: replacementItem,
index: R.findIndex(
originalItem => predicate(originalItem, replacementItem),
originalItems
)
}))
)(replaceWithItems))
usage:
replaceBy((original, updated) => original.id === updated.id, updatedUsers, allUsers)
Updates first item found using given predicate with a new item. To update multiple items use replaceBy
defined above.
const updateBy = R.curry((func, value, target) => {
const index = R.findIndex(func, target);
return index >= 0 ? R.update(index, value, target) : target;
});
usage:
updateBy(x => x === 1, 'hi', [0,1,2,3]) //? [ 0, 'hi', 2, 3 ]
Like R.pluck
, but with string path as a first argument. R.pluck
allows to specify property name, while pluckPath
can work with propert pathes like myProp.otherProp.nestedProp
const pluckPath = R.pipe(
R.split('.'),
R.path,
R.map,
)
const pluckPathCurr = R.curry((path, obj) => pluckPath(path)(obj))
usage:
const list = [
{ x: { y: 1} },
{ x: { y: 2} },
{ x: { y: 3} },
]
pluckPath('x.y')(list) // [1, 2, 3]
Like R.indexBy, but accepts additional tranformation function to transform value for the given key.
const R = require('ramda')
const indexByWith = R.curry((keygenFunc, fn, items) =>
R.reduce(
(acc, item) => {
acc[keygenFunc(item)] = fn(item)
return acc
},
{},
items,
),
)
usage:
indexByWith(R.prop('foo'), item => ({ a: item }), [
{ foo: 1 },
{ foo: 2 },
{ foo: 3 },
])
Like R.reduce, but for objects.
const reduceObj = R.useWith(R.reduce, [R.identity, R.identity, R.toPairs]);
usage:
reduceObj((acc, [key, val]) => return acc, {}, obj)
Recursively traverse object and apply transformer function to every [key, value]
pair and form new object based on that. If transformation function returns undefined
then those [key, value]
paris get removed from the original object. Keeps arrays as-is, meaning object inside an array won't be transformed.
const reduceObj = R.useWith(R.reduce, [R.identity, R.identity, R.toPairs]);
// given key value pair return new key value pair or nothing
const removeEmptyKeysTransformer = ([key, val]) => {
if (val === undefined) {
return undefined;
}
return [key, val];
};
// transformer is a function that takes [key, value] and return transformed pair or undefined
// if undefined is returned that pair is going to be removed from the object. Recursively applied
// properties of the object. Keeps arrays as-is, meaning object inside an array won't be transformed.
// transformer is a function that takes [key, value] and return transformed pair or undefined
// if undefined is returned that pair is going to be removed from the object. Recursively applied
// properties of the object. Keeps arrays as-is, meaning object inside an array won't be transformed.
// Handles circular references.
const transformObjectDeep = R.curry((transformer, obj, objectCache = undefined) => {
const cache = objectCache || new Set();
cache.add(obj);
return reduceObj(
(acc, [key, val]) => {
if (!Array.isArray(val) && val !== null && typeof val === 'object') {
// detecting circular references
if (cache.has(val)) {
log.warn(`π Circular reference detected in "transformObjectDeep", skipping, key=${key}`);
acc[key] = `[Circular]`;
return acc;
}
cache.add(val);
const transformedVal = transformObjectDeep(transformer, val, cache);
acc[key] = transformedVal;
return acc;
}
const transformedKeyVal = transformer([key, val]);
if (transformedKeyVal === undefined) {
return acc;
}
const [tKey, tVal] = transformedKeyVal;
acc[tKey] = tVal;
return acc;
},
{},
obj,
);
});
usage:
// given key value pair return new key value pair or nothing
const removeEmptyKeysTransformer = ([key, val]) => {
if (val === undefined) {
return undefined;
}
return [key, val];
};
transformObjectDeep(removeEmptyKeysTransformer, { x: 8, y: undefined } ); //output: { x: 8 }
Func β [a] β a
Find element in a list that has max value specified in the provided path using path getter function.
const findMaxBy = R.curry((path, arr) =>
R.pipe(R.reduce((acc, x) => (path(acc) > path(x) ? acc : x), {}))(arr),
)
usage:
const prs = [
{ pullRequests: { totalCount: 10 } },
{ pullRequests: { totalCount: 8 } },
{ pullRequests: { totalCount: 20 } },
{ pullRequests: { totalCount: 12 } },
]
findMaxBy(R.path(['pullRequests', 'totalCount']), prs) // outputs: { pullRequests: { totalCount: 20 } }