Security News
PyPI Introduces Digital Attestations to Strengthen Python Package Security
PyPI now supports digital attestations, enhancing security and trust by allowing package maintainers to verify the authenticity of Python packages.
Rambda is a lightweight and fast utility library that provides a variety of functions for functional programming in JavaScript. It is a smaller and faster alternative to Ramda, offering a similar API but with a focus on performance and simplicity.
Currying
Currying is a technique of evaluating functions with multiple arguments, one at a time. Rambda's `curry` function allows you to transform a function so that it can be called with fewer arguments than it expects, returning a new function that takes the remaining arguments.
const R = require('rambda');
const add = R.curry((a, b) => a + b);
const add5 = add(5);
console.log(add5(3)); // 8
Composition
Function composition is the process of combining two or more functions to produce a new function. Rambda's `compose` function allows you to create a pipeline of functions that are executed from right to left.
const R = require('rambda');
const add = (a, b) => a + b;
const multiply = (a, b) => a * b;
const addAndMultiply = R.compose(R.multiply(2), R.add(3));
console.log(addAndMultiply(4)); // 14
Cloning
Cloning is the process of creating a deep copy of an object. Rambda's `clone` function allows you to create a deep copy of an object, ensuring that changes to the new object do not affect the original object.
const R = require('rambda');
const obj = {a: 1, b: 2};
const clonedObj = R.clone(obj);
console.log(clonedObj); // {a: 1, b: 2}
Filtering
Filtering is the process of selecting a subset of items from a collection based on a predicate function. Rambda's `filter` function allows you to filter elements in an array or object based on a provided predicate.
const R = require('rambda');
const isEven = n => n % 2 === 0;
const numbers = [1, 2, 3, 4, 5, 6];
const evenNumbers = R.filter(isEven, numbers);
console.log(evenNumbers); // [2, 4, 6]
Mapping
Mapping is the process of transforming each item in a collection using a provided function. Rambda's `map` function allows you to apply a function to each element in an array or object, returning a new array or object with the transformed elements.
const R = require('rambda');
const double = n => n * 2;
const numbers = [1, 2, 3, 4, 5];
const doubledNumbers = R.map(double, numbers);
console.log(doubledNumbers); // [2, 4, 6, 8, 10]
Lodash is a popular utility library that provides a wide range of functions for common programming tasks. It is more feature-rich compared to Rambda but also larger in size. Lodash focuses on performance and ease of use, offering a comprehensive set of tools for working with arrays, objects, strings, and more.
Underscore is another utility library that provides a variety of functional programming helpers. It is similar to Lodash but with a smaller footprint and fewer features. Underscore offers a core set of functions for working with collections, arrays, objects, and functions, making it a good choice for projects that need a lightweight utility library.
Ramda is a functional programming library for JavaScript that emphasizes immutability and pure functions. It offers a similar API to Rambda but with a larger set of functions and a focus on functional programming principles. Ramda is more feature-rich but also larger in size compared to Rambda.
Faster alternative to Ramda - Documentation
Currenly Rambda is more tree-shakable than Ramda as you can see in this tree-shaking example.
------------------ --------
file size
------------------ --------
rollup/rambdax 206 B
rollup/ramdaBabel 276 B
rollup/lodash 278 B
rollup/rambda 785 B
parcel/lodash 1.2 KB
parcel/rambdax 1.2 KB
parcel/ramda 1.2 KB
parcel/rambda 1.2 KB
parcel/ramdaBabel 1.23 KB
webpack/rambda 2 KB
webpack/ramda 7.3 KB
webpack/ramdaBabel 8.36 KB
webpack/rambdax 26.71 KB
webpack/lodash 70.76 KB
rollup/ramda 92.16 KB
Also latest results of bundle-phobia-cli
:
ℹ ramda (0.26.1) has 0 dependencies for a weight of 51.92KB (12.27KB gzipped)
ℹ rambda (2.1.1) has 0 dependencies for a weight of 13.28KB (3.32KB gzipped)
ℹ rambdax (1.3.0) has 0 dependencies for a weight of 31.52KB (8.95KB gzipped)
Rambda is generally more performant than Ramda
as the benchmarks can prove that.
You can clone this repo and run yarn run benchmark all
to see for yourself.
R.path
Standard usage of R.path
is R.path(['a', 'b'], {a: {b: 1} })
.
In Rambda you have the choice to use dot notation(which is arguably more readable):
R.path('a.b', {a: {b: 1} })
R.pick
and R.omit
Similar to dot notation, but the separator is comma(,
) instead of dot(.
).
R.pick('a,b', {a: 1 , b: 2, c: 3} })
// No space allowed between properties
Typescript definitions are included in the library, in comparison to Ramda, where you need to additionally install @types/ramda
.
Rambda partially shadows Ramda's API, which means that you need to check Rambda's documentation to assure that all the methods you need are available.
import {compose, map, filter} from 'rambda'
const result = compose(
map(x => x * 2),
filter(x => x > 2)
)([1, 2, 3, 4])
// => [6, 8]
You can test this example in Rambda's REPL
Use yarn add rambda for Webpack
and Node.js
usage
For UMD usage either use ./dist/rambda.umd.js
or following CDN link:
https://unpkg.com/rambda@2.0.0/dist/rambda.umd.js
Rambda's type detect async functions and unresolved Promises
. The returned values are 'Async'
and 'Promise'
.
Rambda's path accepts dot notation('x.y' same as ['x','y']
)
Rambda's pick and omit accept comma notation('x,y' same as ['x','y']
)
Rambda's map and filter pass object key as second argument when mapping over objects.
Rambda's map and filter pass array index as second argument when mapping over arrays.
Rambda's all, allPass, any, anyPass, findIndex and reject are passing index as second argument to the predicate function.
Rambda's defaultTo accept indefinite number of arguments when non curried, i.e. R.defaultTo(2, foo, bar, baz)
.
Rambda's startsWith/endsWith work only with strings, instead with array and strings.
Rambda's equals doesn't protect against circular structures as Ramda.equals does.
Rambda's flip works only for functions expecting two arguments.
Rambda's partialCurry is not part of Ramda API.
Rambda's includes acts as curried Javascript includes
, while Ramda version uses R.equals
to check if a list contains certain value. Also Ramda version will throw an error if input is neither string
nor array
, while Rambda version will return false
.
If you need more Ramda methods in Rambda, you may either submit a
PR
or check the extended version of Rambda - Rambdax. In case of the former, you may want to consult with Rambda contribution guidelines.
add(a: number, b: number): number
R.add(2, 3) // => 5
adjust(replaceFn: Function, i: number, arr: T[]): T[]
It replaces i
index in arr
with the result of replaceFn(arr[i])
.
R.adjust(
a => a + 1,
0,
[0, 100]
) // => [1, 100]
all(fn: Function, arr: T[]): boolean
It returns true
, if all members of array arr
returns true
, when applied as argument to function fn
.
const arr = [ 0, 1, 2, 3, 4 ]
const fn = x => x > -1
const result = R.all(fn, arr)
// => true
allPass(rules: Function[], input: any): boolean
It returns true
, if all functions of rules
return true
, when input
is their argument.
const input = {
a : 1,
b : 2,
}
const rules = [
x => x.a === 1,
x => x.b === 2,
]
const result = R.allPass(rules, input) // => true
always(x: any): Function
It returns function that always returns x
.
const fn = R.always(7)
console.log(fn())// => 7
any(condition: Function, arr: T[]): boolean
It returns true
, if at least one member of arr
returns true, when passed to the condition
function.
R.any(a => a * a > 8)([1, 2, 3])
// => true
anyPass(conditions: Function[]): Function
const isBig = a => a > 20
const isOdd = a => a % 2 === 1
const result = R.anyPass(
[isBig, isOdd]
)(11)
// => true
append(valueToAppend: T, arr: T[]): T[]
R.append(
'foo',
['bar', 'baz']
) // => ['bar', 'baz', 'foo']
assoc(prop: any, value: any, obj: object): object
Makes a shallow clone of obj
, setting or overriding the property prop
with
the value value
. Note that this copies and flattens prototype properties
onto the new object as well. All non-primitive properties are copied by
reference.
R.assoc('c', 3, {a: 1, b: 2})
//=> {a: 1, b: 2, c: 3}
both(firstCondition: Function, secondCondition: Function, input: any): boolean
It returns true
, if both function firstCondition
and function secondCondition
return true
, when input
is their argument.
const fn = R.both(
a => a > 10,
a => a < 20
)
console.log(fn(15)) //=> true
console.log(fn(30)) //=> false
compose(fn1: Function, ... , fnN: Function): any
It performs right-to-left function composition.
const result = R.compose(
R.map(x => x * 2),
R.filter(x => x > 2)
)([1, 2, 3, 4])
// => [6, 8]
complement(fn: Function): Function
It returns complemented
function that accept input
as argument.
The return value of complemented
is the negative boolean value of fn(input)
.
const fn = R.complement(x => !x)
const result = fn(false) // => false
concat(x: T[]|string, y: T[]|string): T[]|string
It returns a new string or array, which is the result of merging x
and y
.
R.concat([1, 2])([3, 4]) // => [1, 2, 3, 4]
R.concat('foo')('bar') // => 'foobar'
contains(valueToFind: T, arr: T[]): boolean
It returns true
, if valueToFind
is part of arr
.
Note that while new versions of Ramda
depricate this method, contains
will remain in this library.
R.contains(2, [1, 2]) // => true
R.contains(3, [1, 2]) // => false
curry(fn: Function): Function
It returns curried version of fn
.
const addFourNumbers = (a, b, c, d) => a + b + c + d
const curriedAddFourNumbers = R.curry(addFourNumbers)
const f = curriedAddFourNumbers(1, 2)
const g = f(3)
const result = g(4) // => 10
dec(x: number): number
It decrements a number.
R.dec(2) // => 1
defaultTo(defaultValue: T, ...inputArguments: any[]): T
It either returns defaultValue
, if all of inputArguments
are undefined
, null
or NaN
.
Or it returns the first truthy inputArguments
instance(from left to right).
R.defaultTo('foo', undefined) // => 'foo'
R.defaultTo('foo', undefined, null, NaN) // => 'foo'
R.defaultTo('foo', undefined, 'bar', NaN, 'baz') // => 'bar'
R.defaultTo('foo', undefined, null, NaN, 'baz') // => 'baz'
R.defaultTo('foo', 'bar') // => 'bar'
dissoc(prop: any, obj: object): object
It returns a new object that does not contain a prop
property.
R.dissoc('b', {a: 1, b: 2, c: 3})
//=> {a: 1, c: 3}
R.divide(71, 100) // => 0.71
drop(howManyToDrop: number, arrOrStr: T[]|string): T[]|String
It returns arrOrStr
with howManyToDrop
items dropped from the left.
R.drop(1, ['foo', 'bar', 'baz']) // => ['bar', 'baz']
R.drop(1, 'foo') // => 'oo'
dropLast(howManyToDrop: number, arrOrStr: T[]|String): T[]|String
It returns arrOrStr
with howManyToDrop
items dropped from the right.
R.dropLast(1, ['foo', 'bar', 'baz']) // => ['foo', 'bar']
R.dropLast(1, 'foo') // => 'fo'
endsWith(x: string, str: string): boolean
R.endsWith(
'bar',
'foo-bar'
) // => true
R.endsWith(
'foo',
'foo-bar'
) // => false
either(firstCondition: Function, secondCondition: Function): Function
R.either(
a => a > 10,
a => a % 2 === 0
)(15) //=> true
equals(a: any, b: any): boolean
It returns equality match between a
and b
.
It doesn't handle cyclical data structures.
R.equals(
[1, {a:2}, [{b:3}]],
[1, {a:2}, [{b:3}]]
) // => true
R.F() // => false
filter(filterFn: Function, x: Array|Object): Array|Object
It filters x
iterable over boolean returning filterFn
.
const filterFn = a => a % 2 === 0
const result = R.filter(filterFn, [1, 2, 3, 4])
// => [2, 4]
The method works with objects as well.
Note that unlike Ramda's filter
, here object keys are passed as second argument to filterFn
.
const result = R.filter((val, prop)=>{
return prop === 'a' || val === 2
}, {a: 1, b: 2, c: 3})
// => {a: 1, b: 2}
find(findFn: Function, arr: T[]): T|undefined
It returns undefined
or the first element of arr
satisfying findFn
.
const findFn = a => R.type(a.foo) === 'Number'
const arr = [{foo: 'bar'}, {foo: 1}]
const result = R.find(findFn, arr)
// => {foo: 1}
findIndex(findFn: Function, arr: T[]): number
It returns -1
or the index of the first element of arr
satisfying findFn
.
const findFn = a => R.type(a.foo) === 'Number'
const arr = [{foo: 'bar'}, {foo: 1}]
const result = R.findIndex(findFn, arr)
// => 1
flatten(arr: any[]): any[]
R.flatten([ 1, [ 2, [ 3 ] ] ])
// => [ 1, 2, 3 ]
flip(fn: Function): Function
It returns function which calls fn
with exchanged first and second argument.
const subtractFlip = R.flip(R.subtract)
const result = subtractFlip(1,7)
// => 6
forEach(fn: Function, arr: Array): Array
It applies function fn
over all members of array arr
and returns arr
.
const sideEffect = {}
const result = R.forEach(
x => sideEffect[`foo${x}`] = x
)([1, 2])
console.log(sideEffect) //=> {foo1 : 1, foo2 : 2}
console.log(result) //=> [1, 2]
Note, that unlike Ramda
's forEach, Rambda's one doesn't dispatch to forEach
method of arr
if arr
has such method.
groupBy(fn: Function, arr: Array): Object
It groups array arr
by provided selector function fn
.
R.groupBy(
x => x.length,
[ 'a', 'b', 'aa', 'bb' ]
)
// => { '1': ['a', 'b'], '2': ['aa', 'bb'] }
has(prop: string, obj: Object): boolean
true
if obj
has property prop
.R.has('a', {a: 1}) // => true
R.has('b', {a: 1}) // => false
head(arrOrStr: T[]|string): T|string
It returns the first element of arrOrStr
.
R.head([1, 2, 3]) // => 1
R.head('foo') // => 'f'
identity(x: T): T
It just passes back the supplied arguments.
R.identity(7) // => 7
ifElse(condition: Function|boolean, ifFn: Function, elseFn: Function): Function
It returns function, which expect input
as argument and returns finalResult
.
When this function is called, a value answer
is generated as a result of condition(input)
.
If answer
is true
, then finalResult
is equal to ifFn(input)
.
If answer
is false
, then finalResult
is equal to elseFn(input)
.
const fn = R.ifElse(
x => x > 10,
x => x*2,
x => x*10
)
const result = fn(8)
// => 80
inc(x: number): number
It increments a number.
R.inc(1) // => 2
If input
is neither string
nor array
, then this method will return false
.
includes(target: any, input: any): boolean
R.includes(1, [1, 2]) // => true
R.includes('oo', 'foo') // => true
R.includes('z', 'foo') // => false
R.includes('z', null) // => false
!! Note that this method is not part of Ramda
API.
indexBy(fn: Function, arr: T[]): Object
It indexes array arr
as an object with provided selector function fn
.
R.indexBy(
x => x.id,
[ {id: 1}, {id: 2} ]
)
// => { 1: {id: 1}, 2: {id: 2} }
indexOf(valueToFind: any, arr: T[]): number
It returns -1
or the index of the first element of arr
equal of valueToFind
.
R.indexOf(1, [1, 2]) // => 0
R.indexOf(0, [1, 2]) // => -1
init(arrOrStr: T[]|string): T[]|string
arrOrStr
.R.init([1, 2, 3]) // => [1, 2]
R.init('foo') // => 'fo'
is(xPrototype: any, x: any): boolean
It returns true
is x
is instance of xPrototype
.
R.is(String, 'foo') // => true
R.is(Array, 1) // => false
isNil(x: any): boolean
It returns true
is x
is either null
or undefined
.
R.isNil(null) // => true
R.isNil(1) // => false
join(separator: string, arr: T[]): string
R.join('-', [1, 2, 3]) // => '1-2-3'
keys(x: Object): string[]
R.keys({a:1, b:2}) // => ['a', 'b']
last(arrOrStr: T[]|string): T|string
arrOrStr
.R.last(['foo', 'bar', 'baz']) // => 'baz'
R.last('foo') // => 'o'
lastIndexOf(x: any, arr: T[]): number
It returns the last index of x
in array arr
.
R.equals
is used to determine equality between x
and members of arr
.
Value -1
is returned if no x
is found in arr
.
R.lastIndexOf(1, [1, 2, 3, 1, 2]) // => 3
R.lastIndexOf(10, [1, 2, 3, 1, 2]) // => -1
length(arrOrStr: Array|String): Number
R.length([1, 2, 3]) // => 3
map(mapFn: Function, x: Array|Object): Array|Object
It returns the result of looping through iterable x
with mapFn
.
The method works with objects as well.
Note that unlike Ramda's map
, here object keys are passed as second argument to mapFn
.
const mapFn = x => x * 2
const resultWithArray = R.map(mapFn, [1, 2, 3])
// => [2, 4, 6]
const result = R.map((val, prop)=>{
return `${prop}-${val}`
}, {a: 1, b: 2})
// => {a: 'a-1', b: 'b-2'}
match(regExpression: Regex, str: string): string[]
R.match(/([a-z]a)/g, 'bananas') // => ['ba', 'na', 'na']
max(x: Number|String, y: Number|String): Number|String
R.max(5,7) // => 7
maxBy(fn: Function, x: Number|String, y: Number|String): Number|String
R.maxBy(Math.abs, 5, -7) // => -7
merge(a: Object, b: Object)
It returns result of Object.assign({}, a, b)
.
R.merge({ 'foo': 0, 'bar': 1 }, { 'foo': 7 })
// => { 'foo': 7, 'bar': 1 }
min(x: Number|String, y: Number|String): Number|String
R.max(5,7) // => 5
minBy(fn: Function, x: Number|String, y: Number|String): Number|String
R.minBy(Math.abs, -5, -7) // => -5
modulo(a: number, b: number):numberNumber
It returns the remainder of operation a/b
.
R.module(14, 3) // => 2
multiply(a: number, b: number): number
It returns the result of operation a*b
.
R.multiply(4, 3) // => 12
not(x: any): boolean
It returns inverted boolean version of input x
.
R.not(true) //=> false
R.not(false) //=> true
R.not(0) //=> true
R.not(1) //=> false
omit(propsToOmit: string[]|string, obj: Object): Object
It returns a partial copy of an obj
with omitting propsToOmit
R.omit('a,c,d', {a: 1, b: 2, c: 3}) // => {b: 2}
path(pathToSearch: string[]|string, obj: Object): any
If pathToSearch
is 'a.b'
then it will return 1
if obj
is {a:{b:1}}
.
It will return undefined
, if such path is not found.
R.path('a.b', {a: {b: 1}}) // => 1
pathOr(defaultValue: any, pathToSearch: string[]|string, obj: Object): any
pathFound
is the result of calling R.path(pathToSearch, obj)
.
If pathFound
is undefined
, null
or NaN
, then defaultValue
will be returned.
pathFound
is returned in any other case.
R.pathOr(1, 'a.b', {a: {b: 2}}) // => 2
R.pathOr(1, ['a', 'b'], {a: {b: 2}}) // => 2
R.pathOr(1, ['a', 'c'], {a: {b: 2}}) // => 1
partialCurry(fn: Function|Async, a: Object, b: Object): Function|Promise
When called with function fn
and first set of input a
, it will return a function.
This function will wait to be called with second set of input b
and it will invoke fn
with the merged object of a
over b
.
fn
can be asynchronous function. In that case a Promise
holding the result of fn
is returned.
See the example below:
const fn = ({a, b, c}) => {
return (a * b) + c
}
const curried = R.partialCurry(fn, {a: 2})
const result = curried({b: 3, c: 10})
// => 16
Note that partialCurry
is method specific for Rambda and the method is not part of Ramda's API
You can read my argumentation for creating partialCurry here
pick(propsToPick: string[], obj: Object): Object
It returns a partial copy of an obj
containing only propsToPick
properties.
R.pick(['a', 'c'], {a: 1, b: 2}) // => {a: 1}
pipe(fn1: Function, ... , fnN: Function): any
It performs left-to-right function composition.
const result = R.pipe(
R.filter(val => val > 2),
R.map(a => a * 2)
)([1, 2, 3, 4])
// => [6, 8]
pluck(property: string, arr: Object[]): any[]
It returns list of the values of property
taken from the objects in array of objects arr
.
R.pluck('a')([{a: 1}, {a: 2}, {b: 3}]) // => [1, 2]
prepend(x: T, arr: T[]): T[]
It adds x
to the start of the array arr
.
R.prepend('foo', ['bar', 'baz']) // => ['foo', 'bar', 'baz']
prop(propToFind: string, obj: Object): any
It returns undefined
or the value of property propToFind
in obj
R.prop('x', {x: 100}) // => 100
R.prop('x', {a: 1}) // => undefined
propEq(propToFind: string, valueToMatch: any, obj: Object): boolean
It returns true if obj
has property propToFind
and its value is equal to valueToMatch
.
const propToFind = 'foo'
const valueToMatch = 0
const result = R.propEq(propToFind, valueToMatch)({foo: 0})
// => true
range(start: number, end: number): number[]
It returns a array of numbers from start
(inclusive) to end
(exclusive).
R.range(0, 3) // => [0, 1, 2]
reduce(iteratorFn: Function, accumulator: any, array: T[]): any
const iteratorFn = (acc, val) => acc + val
const result = R.reduce(iteratorFn, 1, [1, 2, 3])
// => 7
reject(fn: Function, arr: T[]): T[]
It has the opposite effect of R.filter
.
It will return those members of arr
that return false
when applied to function fn
.
const fn = x => x % 2 === 1
const result = R.reject(fn, [1, 2, 3, 4])
// => [2, 4]
repeat(valueToRepeat: T, num: number): T[]
R.repeat('foo', 2) // => ['foo', 'foo']
replace(strOrRegex: string|Regex, replacer: string, str: string): string
It replaces strOrRegex
found in str
with replacer
.
R.replace('foo', 'bar', 'foo foo') // => 'bar foo'
R.replace(/foo/, 'bar', 'foo foo') // => 'bar foo'
R.replace(/foo/g, 'bar', 'foo foo') // => 'bar bar'
reverse(str: T[]): T[]
const arr = [1, 2]
const result = R.reverse(arr)
// => [2, 1]
sort(sortFn: Function, arr: T[]): T[]
It returns copy of arr
sorted by sortFn
.
Note that sortFn
must return a number type.
const sortFn = (a, b) => a - b
const result = R.sort(sortFn, [3, 1, 2])
// => [1, 2, 3]
sortBy(sortFn: Function, arr: T[]): T[]
It returns copy of arr
sorted by sortFn
.
Note that sortFn
must return value for comparison.
const sortFn = obj => obj.foo
const result = R.sortBy(sortFn, [
{foo: 1},
{foo: 0}
])
const expectedResult = [ {foo: 0}, {foo: 1} ]
console.log(R.equals(result, expectedResult))
// => true
split(separator: string, str: string): string[]
R.split('-', 'a-b-c') // => ['a', 'b', 'c']
splitEvery(sliceLength: number, arrOrString: T[]|string): T[T[]]|string[]
arrOrStr
into slices of sliceLength
.R.splitEvery(2, [1, 2, 3]) // => [[1, 2], [3]]
R.splitEvery(3, 'foobar') // => ['foo', 'bar']
startsWith(x: string, str: string): boolean
R.startsWith(
'foo',
'foo-bar'
) // => true
R.startsWith(
'bar',
'foo-bar'
) // => false
subtract(a: number, b: number): number
R.subtract(3, 1) // => 2
R.T() // => true
tail(arrOrStr: T[]|string): T[]|string
arrOrStr
R.tail([1, 2, 3]) // => [2, 3]
R.tail('foo') // => 'oo'
take(num: number, arrOrStr: T[]|string): T[]|string
num
elements of arrOrStr
.R.take(1, ['foo', 'bar']) // => ['foo']
R.take(2, ['foo']) // => 'fo'
takeLast(num: number, arrOrStr: T[]|string): T[]|string
num
elements of arrOrStr
.R.takeLast(1, ['foo', 'bar']) // => ['bar']
R.takeLast(2, ['foo']) // => 'oo'
tap(fn: Function, input: T): T
num
elements of arrOrStr
.let a = 1
const sayX = x => (a = x)
const result = R.tap(sayX, 100)
// both `a` and `result` are `100`
test(regExpression: Regex, str: string): boolean
str
matches regExpression
R.test(/^f/, 'foo')
// => true
times(fn: Function, n: number): T[]
It returns the result of applying function fn
over members of range array.
The range array includes numbers between 0
and n
(exclusive).
R.times(R.identity, 5)
//=> [0, 1, 2, 3, 4]
toLower(str: string): string
R.toLower('FOO') // => 'foo'
toString(x: any): string
R.toString([1, 2]) // => '1,2'
toUpper(str: string): string
R.toUpper('foo') // => 'FOO'
trim(str: string): string
R.trim(' foo ') // => 'foo'
type(a: any): string
R.type(() => {}) // => 'Function'
R.type(async () => {}) // => 'Async'
R.type([]) // => 'Array'
R.type({}) // => 'Object'
R.type('foo') // => 'String'
R.type(1) // => 'Number'
R.type(true) // => 'Boolean'
R.type(null) // => 'Null'
R.type(/[A-z]/) // => 'RegExp'
const delay = ms => new Promise(resolve => {
setTimeout(function () {
resolve()
}, ms)
})
R.type(delay) // => 'Promise'
uniq(arr: T[]): T[]
It returns a new array containing only one copy of each element in arr
.
R.uniq([1, 1, 2, 1])
// => [1, 2]
uniqWith(fn: Function, arr: T[]): T[]
It returns a new array containing only one copy of each element in arr
according to boolean returning function fn
.
const arr = [
{id: 0, title:'foo'},
{id: 1, title:'bar'},
{id: 2, title:'baz'},
{id: 3, title:'foo'},
{id: 4, title:'bar'},
]
const expectedResult = [
{id: 0, title:'foo'},
{id: 1, title:'bar'},
{id: 2, title:'baz'},
]
const fn = (x,y) => x.title === y.title
const result = R.uniqWith(fn, arr)
console.log(R.equals(result, expectedResult)) // => true
update(i: number, replaceValue: T, arr: T[]): T[]
It returns a new copy of the arr
with the element at i
index
replaced with replaceValue
.
R.update(0, 'foo', ['bar', 'baz'])
// => ['foo', baz]
values(obj: Object): Array
It returns array with of all values in obj
.
R.values({a: 1, b: 2})
// => [1, 2]
without(a: T[], b: T[]): T[]
It will return a new array based on b
array.
This array contains all members of b
array, that doesn't exist in a
array.
Method R.equals
is used to determine the existance of b
members in a
array.
R.without([1, 2], [1, 2, 3, 4])
// => [3, 4]
zip(a: K[], b: V[]): Array
It will return a new array containing tuples of equally positions items from both lists. The returned list will be truncated to match the length of the shortest supplied list.
R.zip([1, 2], ['A', 'B'])
// => [[1, 'A'], [2, 'B']]
// truncates to shortest list
R.zip([1, 2, 3, 4], ['A', 'B'])
// => [[1, 'A'], [2, 'B']]
zipObj(a: K[], b: V[]): Object
It will return a new object with keys of a
array and values of b
array.
R.zipObj(['a', 'b', 'c'], [1, 2, 3])
//=> {a: 1, b: 2, c: 3}
// truncates to shortest list
R.zipObj(['a', 'b', 'c'], [1, 2])
//=> {a: 1, b: 2}
Results of running yarn benchmarks
:
Running add.js
3 tests completed.
Rambda.add x 645,750,977 ops/sec ±1.21% (89 runs sampled)
Ramda.add x 61,329,732 ops/sec ±4.57% (75 runs sampled)
Lodash.add x 49,915,718 ops/sec ±5.72% (74 runs sampled)
Running adjust.js
2 tests completed.
Rambda.adjust x 2,356,436 ops/sec ±4.24% (72 runs sampled)
Ramda.adjust x 8,249,572 ops/sec ±3.41% (76 runs sampled)
Running any.js
3 tests completed.
Rambda.any x 14,673,511 ops/sec ±4.50% (74 runs sampled)
Ramda.any x 3,227,456 ops/sec ±5.51% (74 runs sampled)
Lodash.some x 11,964,478 ops/sec ±3.52% (74 runs sampled)
Running append.js
2 tests completed.
Rambda.append x 3,020,920 ops/sec ±6.56% (70 runs sampled)
Ramda x 2,381,626 ops/sec ±8.22% (74 runs sampled)
Running assoc.js
3 tests completed.
Rambda.assoc x 1,091,819 ops/sec ±3.44% (82 runs sampled)
Ramda.assoc x 5,780,540 ops/sec ±7.26% (75 runs sampled)
Lodash.set x 7,025,930 ops/sec ±2.93% (84 runs sampled)
Running compose.js
3 tests completed.
Rambda.compose x 9,908,504 ops/sec ±7.20% (80 runs sampled)
Ramda x 490,614 ops/sec ±3.65% (93 runs sampled)
Lodash.flowRight x 1,947,909 ops/sec ±3.05% (83 runs sampled)
Running contains.js
3 tests completed.
Rambda.contains x 9,829,102 ops/sec ±5.41% (71 runs sampled)
Ramda x 20,822,670 ops/sec ±7.20% (81 runs sampled)
Lodash.includes x 13,424,597 ops/sec ±1.43% (93 runs sampled)
Running drop.js
2 tests completed.
Rambda.drop x 13,421,844 ops/sec ±1.96% (94 runs sampled)
Ramda x 1,299,620 ops/sec ±0.56% (90 runs sampled)
Running dropLast.js
2 tests completed.
Rambda.dropLast x 12,256,336 ops/sec ±2.98% (83 runs sampled)
Ramda x 979,827 ops/sec ±0.85% (91 runs sampled)
Running endsWith.js
2 tests completed.
Rambda.endsWith:
Ramda.endsWith x 244,130 ops/sec ±0.80% (93 runs sampled)
Running equals.js
3 tests completed.
Rambda.equals x 776,908 ops/sec ±0.36% (95 runs sampled)
Ramda x 130,283 ops/sec ±0.27% (96 runs sampled)
Lodash.isEqual x 324,492 ops/sec ±1.54% (91 runs sampled)
Running filter.js
3 tests completed.
Rambda.filter x 8,972,564 ops/sec ±0.70% (93 runs sampled)
Ramda x 2,828,593 ops/sec ±1.28% (92 runs sampled)
Lodash x 7,988,026 ops/sec ±0.53% (91 runs sampled)
Running find.js
3 tests completed.
Rambda.find x 15,377,832 ops/sec ±1.19% (94 runs sampled)
Ramda x 3,552,442 ops/sec ±1.43% (93 runs sampled)
Lodash x 6,795,695 ops/sec ±2.68% (83 runs sampled)
Running findIndex.js
3 tests completed.
Rambda.findIndex x 74,769,765 ops/sec ±1.47% (89 runs sampled)
Ramda x 4,495,595 ops/sec ±0.29% (86 runs sampled)
Lodash x 18,412,494 ops/sec ±0.69% (94 runs sampled)
Running flatMap.js
3 tests completed.
Rambda.flatMap:
Ramda.chain x 693,304 ops/sec ±0.60% (92 runs sampled)
Lodash.flatMap x 5,010,798 ops/sec ±2.65% (91 runs sampled)
Running flatten.js
3 tests completed.
Rambda.flatten x 11,422,824 ops/sec ±0.76% (83 runs sampled)
Ramda x 511,591 ops/sec ±1.15% (93 runs sampled)
Lodash x 11,886,203 ops/sec ±4.04% (90 runs sampled)
Running head.js
3 tests completed.
Rambda.head x 666,523,533 ops/sec ±2.28% (90 runs sampled)
Ramda x 4,108,249 ops/sec ±2.61% (81 runs sampled)
Lodash x 635,064,083 ops/sec ±2.33% (90 runs sampled)
Running headString.js
2 tests completed.
Rambda.head when string x 657,989,058 ops/sec ±2.97% (92 runs sampled)
Ramda x 4,359,516 ops/sec ±2.60% (90 runs sampled)
Running indexOf.js
3 tests completed.
Rambda.indexOf x 70,001,108 ops/sec ±1.58% (88 runs sampled)
Ramda x 29,813,338 ops/sec ±1.77% (83 runs sampled)
Lodash x 113,836,928 ops/sec ±3.19% (84 runs sampled)
Running init.js
3 tests completed.
Rambda.init x 65,121,775 ops/sec ±0.55% (90 runs sampled)
Ramda x 3,826,157 ops/sec ±1.67% (90 runs sampled)
Lodash x 65,335,623 ops/sec ±0.53% (94 runs sampled)
Running initString.js
2 tests completed.
Rambda.init when string x 668,106,421 ops/sec ±0.28% (94 runs sampled)
Ramda x 1,859,185 ops/sec ±0.39% (92 runs sampled)
Running last.js
3 tests completed.
Rambda.last x 685,930,416 ops/sec ±0.68% (92 runs sampled)
Ramda x 4,691,688 ops/sec ±0.40% (92 runs sampled)
Lodash x 661,001,582 ops/sec ±0.15% (92 runs sampled)
Running map.js
3 tests completed.
Rambda.map x 38,639,887 ops/sec ±2.84% (85 runs sampled)
Ramda x 3,183,185 ops/sec ±0.56% (90 runs sampled)
Lodash x 10,962,353 ops/sec ±0.67% (95 runs sampled)
Running match.js
2 tests completed.
Rambda.match x 5,426,665 ops/sec ±0.86% (91 runs sampled)
Ramda x 2,047,681 ops/sec ±1.77% (91 runs sampled)
Running merge.js
3 tests completed.
Rambda.merge x 1,863,285 ops/sec ±1.01% (94 runs sampled)
Ramda x 1,697,063 ops/sec ±0.57% (93 runs sampled)
Lodash x 3,204,496 ops/sec ±1.92% (93 runs sampled)
Running omit.js
3 tests completed.
Rambda.omit x 16,131,957 ops/sec ±2.29% (88 runs sampled)
Ramda x 5,550,336 ops/sec ±1.11% (87 runs sampled)
Lodash x 462,267 ops/sec ±0.48% (95 runs sampled)
Running path.js
3 tests completed.
Rambda.path x 19,324,789 ops/sec ±2.32% (84 runs sampled)
Ramda x 12,023,590 ops/sec ±0.56% (94 runs sampled)
Lodash.get x 23,917,540 ops/sec ±0.20% (91 runs sampled)
Running pick.js
3 tests completed.
Rambda#pick x 14,718,599 ops/sec ±1.11% (90 runs sampled)
Ramda x 2,743,200 ops/sec ±2.89% (88 runs sampled)
Lodash x 1,163,711 ops/sec ±0.65% (85 runs sampled)
Running pipe.js
3 tests completed.
Rambda.pipe x 4,882,396 ops/sec ±2.63% (84 runs sampled)
Ramda x 684,076 ops/sec ±0.36% (93 runs sampled)
Lodash.flow x 2,249,643 ops/sec ±2.35% (87 runs sampled)
Running prop.js
2 tests completed.
Rambda#prop x 24,454,343 ops/sec ±2.82% (77 runs sampled)
Ramda x 2,465,343 ops/sec ±3.22% (86 runs sampled)
Running propEq.js
2 tests completed.
Rambda#propEq x 21,726,907 ops/sec ±2.71% (83 runs sampled)
Ramda x 2,529,510 ops/sec ±0.46% (92 runs sampled)
Running range.js
3 tests completed.
Rambda#range x 17,206,190 ops/sec ±0.96% (92 runs sampled)
Ramda x 10,920,367 ops/sec ±2.85% (86 runs sampled)
Lodash x 15,615,720 ops/sec ±2.36% (89 runs sampled)
Running reduce.js
3 tests completed.
Rambda#reduce x 9,780,084 ops/sec ±2.58% (88 runs sampled)
Ramda x 2,606,911 ops/sec ±1.13% (91 runs sampled)
Lodash x 8,901,216 ops/sec ±0.85% (9
import omit from 'rambda/lib/omit'
2.3.0 Close issue #89 | Fix missing Number
TS definition in R.type
2.2.0 R.defaultTo
accepts indefinite number of input arguments. So the following is valid expression: const x = defaultTo('foo',null, null, 'bar')
2.1.0 Restore R.zip
using WatermelonDB implementation.
2.0.0 Major version caused by removing of R.zip
and R.addIndex
. Issue #85 rightfully finds that the implementation of R.addIndex
is not correct. This led to removing this method and also of R.zip
as it had depended on it. The second change is that R.map
, R.filter
are passing array index as second argument when looping over arrays. The third change is that R.includes
will return false
if input is neigher string
nor array
. The previous behaviour was to throw an error. The last change is to increase the number of methods that are passing index as second argument to the predicate function.
1.2.6 Use src
folder instead of modules
1.2.5 Fix omit
typing
1.2.4 Add missing Typescript definitions - PR#82
1.2.3 Doesn't exist because NPM is great at handling errors.
1.2.2 Change curry method used across most of library methods
1.2.1 Add R.assoc
| fix passing undefined
to R.map
and R.merge
issue #77
1.2.0 Add R.min
, R.minBy
, R.max
, R.maxBy
, R.nth
and R.keys
1.1.5 Close issue #74 R.zipObj
1.1.4 Close issue #71 CRA fail to build rambda
1.1.2 Approve PR #67 use babel-plugin-annotate-pure-calls
1.1.1 Approve PR #66 R.zip
1.1.0 R.compose
accepts more than one input argument issue #65
1.0.13 Approve PR #64 R.indexOf
1.0.12 Close issue #61 make all functions modules
1.0.11 Close issue #60 problem with babelrc
1.0.10 Close issue #59 add R.dissoc
1.0.9 Close issue #58 - Incorrect R.equals
1.0.8 R.map
and R.filter
pass object properties when mapping over objects
1.0.7 Add R.uniqWith
1.0.6 Close issue #52 - ES5 compatible code
1.0.5 Close issue #51
1.0.4 Close issue #50 - add R.pipe
typings
1.0.3 R.ifElse
accept also boolean as condition argument
1.0.2 Remove typedDefaultTo
and typedPathOr
| Add R.pickAll
and R.none
1.0.0 Major change as build is now ES6 not ES5 compatible (Related to issue #46)| Making Rambda
fully tree-shakeable| Edit Typescript definition
0.9.8 Revert to ES5 compatible build - issue #46
0.9.7 Refactor for Rollup
tree-shake | Remove R.padEnd
and R.padStart
0.9.6 Close issue #44 - R.reverse
mutates the array
0.9.5 Close issue #45 - invalid Typescript typings
0.9.4 Add R.reject
and R.without
(PR#41 PR#42) | Remove 'browser' field in package.json
due to Webpack bug 4674
0.9.3 Add R.forEach
and R.times
0.9.2 Add Typescript
definitions
0.9.1 Close issue #36 - move current behaviour of defaultTo
to a new method typedDefaultTo
; make defaultTo
follow Ramda spec; add pathOr
; add typedPathOr
.
0.9.0 Add R.pipe
PR#35
0.8.9 Add R.isNil
0.8.8 Migrate to ES modules PR33 | Add R.flip to the API | R.map/filter works with objects
0.8.7 Change Webpack
with Rollup
- PR29
0.8.6 Add R.tap
and R.identity
0.8.5 Add R.all
, R.allPass
, R.both
, R.either
and R.complement
0.8.4 Learning to run yarn test
before yarn publish
the hard way
0.8.3 Add R.always
, R.T
and R.F
0.8.2 Add concat
, padStart
, padEnd
, lastIndexOf
, toString
, reverse
, endsWith
and startsWith
methods
0.8.1 Add R.ifElse
0.8.0 Add R.not
, R.includes
| Take string as condition for R.pick
and R.omit
0.7.6 Fix incorrect implementation of R.values
0.7.5 Fix incorrect implementation of R.omit
0.7.4 issue #13 - Fix R.curry
, which used to return incorrectly function
when called with more arguments
0.7.3 Close issue #9 - Compile to es2015
; Approve PR #10 - add R.addIndex
to the API
0.7.2 Add Promise
support for R.type
0.7.1 Close issue #7 - add R.reduce
to the API
0.7.0 Close issue #5 - change name of curry
to partialCurry
; add new method curry
, which works just like Ramda's curry
0.6.2 Add separate documentation site via docsify
Running benchmarks
yarn run benchmark all
yarn run benchmark add compose filter
Projects using Rambda
Projects using Rambdax
Articles about Rambda
Links to Rambda
(https://mailchi.mp/webtoolsweekly/web-tools-280)[Web Tools Weekly]
(https://github.com/docsifyjs/awesome-docsify)[awesome-docsify]
FAQs
Lightweight and faster alternative to Ramda with included TS definitions
We found that rambda demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
PyPI now supports digital attestations, enhancing security and trust by allowing package maintainers to verify the authenticity of Python packages.
Security News
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.