Faster alternative to Ramda - Documentation
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
- Install
- Differences between Rambda and Ramda
- API
- Benchmark
- Use with ES5
- Changelog
- Additional info
- Browse by category
- Tree-shaking
Currently Rambda is more tree-shakable than Ramda
- Speed
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.
- dot notation for
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} })
- comma notation for
R.pickandR.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 included
Typescript definitions are included in the library, in comparison to Ramda, where you need to additionally install @types/ramda.
- More generic methods
Ramda has an overwhelming list of methods, as one could get lost putting all the methods in one's head. Rambda's much smaller number of total methods(109) I see as advantage compared to the 255 of Ramda.
Ramda methods has plenty of really deep FP Methods, which are in fact really great, but they come at the price of added complexity. Such complex mechanism in practice are rarely needed.
You can check the list with missing Ramda methods in Rambda list to assure that Rambda doesn't have any important misses.
-
Use yarn add rambda for
WebpackandNode.jsusage -
For UMD usage either use
./dist/rambda.umd.jsor following CDN link:
https://unpkg.com/[email protected]/dist/rambda.umd.js
-
Rambda's type detect async functions and unresolved
Promises. The returned values are'Async'and'Promise'. -
Rambda's type handle
Not a numbervalues and it returnsNaNin this case. -
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 adjust, 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 partial doesn't need the input arguments to be wrapped as array.
-
Rambda's partialCurry is not part of Ramda API.
-
Rambda's includes acts as curried Javascript
includes, while Ramda version usesR.equalsto check if a list contains certain value. Also Ramda version will throw an error if input is neitherstringnorarray, while Rambda version will returnfalse.
If you need more Ramda methods in Rambda, you may either submit a
PRor 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
clone(objOrArr: T|T[]): T|T[] both Creates a deep copy of the value which may contain (nested) Arrays and Objects, Numbers, Strings, Booleans and Dates. Functions are assigned by reference rather than copied
const objects = [{}, {}, {}];
const objectsClone = R.clone(objects);
objects === objectsClone; //=> false
objects[0] === objectsClone[0]; //=> false
compose(fn1: Function, ... , fnN: Function): any
It performs right-to-left function composition.
const result = R.compose(
R.map(x => x * 2),both
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.
fromPairs(list: any[]): object
It transforms a list to an object.
const list = [ [ 'a', 1 ], [ 'b', 2 ], [ 'c', [ 3, 4 ] ] ]
const expected = {
a : 1,
b : 2,
c : [ 3, 4 ],
}
const result = R.fromPairs(list)
// expected === result
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'] }
groupWith(fn: Function, arr: Array): Object
It creates a groups of array members defined by equality function fn.
const list = [ 4, 3, 6, 2, 2, 1 ]
const result = R.groupWith(
(a,b) => a - b === 0,
list
)
const expected = [
[ 4, 3 ],
[ 6 ],
[ 2 ],
[ 2, 1 ],
]
// result === expected
has(prop: string, obj: Object): boolean
- It returns
trueifobjhas propertyprop.
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'
identical(a: any, b: any): boolean
Returns true if its arguments are identical, false otherwise. Values are identical if they reference the same memory. NaN is identical to NaN; 0 and -0 are not identical.
const o = {};
R.identical(o, o); //=> true
R.identical(1, 1); //=> true
R.identical(1, '1'); //=> false
R.identical([], []); //=> false
R.identical(0, -0); //=> false
R.identical(NaN, NaN); //=> true
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
- It returns all but the last element of
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
isEmpty(x: any): boolean
It returns true is x is empty.
R.isEmpty(null) // => true
R.isEmpty(undefined) // => true
R.isEmpty('') // => true
R.isEmpty([]) // => true
R.isEmpty({}) // => true
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
- It returns the last element of
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 array 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
partial(fn: Function, ...inputs: any[]): Function | any
It is very similar to R.curry, but you can pass initial arguments when you create the curried function.
R.partial will keep returning a function until all the arguments that the function fn expects are passed.
The name comes from the fact that you partially inject the inputs.
const fn = (salutation, title, firstName, lastName) => salutation + ', ' + title + ' ' + firstName + ' ' + lastName + '!'
const canPassAnyNumberOfArguments = partial(fn, 'Hello', 'Ms.')
const finalFn = canPassAnyNumberOfArguments('foo')
finalFn('bar') // => 'Hello, Ms. foo bar!'
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
partialCurryis 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
propIs(type: any, name: string, obj: Object): boolean
It Returns true if the specified object property is of the given type.
R.propIs(Number, 'x', {x: 1, y: 2}); //=> true
R.propIs(Number, 'x', {x: 'foo'}); //=> false
R.propIs(Number, 'x', {}); //=> false
propOr(defaultValue: any, param: string, obj: Object): any
If the given, non-null object has an own property with the specified name, returns the value of that property. Otherwise returns the provided default value.
const theWall = { mother: 'Waters', comfortablyNumb: 'Gilmour/Waters' }
const authorOfWishYouWereHere = R.prop('wishYouWereHere')
const authorOfAtomHeartMotherWhenDefault = R.propOr('Pink Floyd', 'atomHeartMother')
authorOfWishYouWereHere(theWall) //=> undefined
authorOfAtomHeartMotherWhenDefault(theWall) //=> 'Pink Floyd'
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[]
- It splits
arrOrStrinto slices ofsliceLength.
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
sum(listOfNumbers: number[]): number
R.sum([1,2,3,4,5]) // => 15
R.T() // => true
tail(arrOrStr: T[]|string): T[]|string
- It returns all but the first element of
arrOrStr
R.tail([1, 2, 3]) // => [2, 3]
R.tail('foo') // => 'oo'
take(num: number, arrOrStr: T[]|string): T[]|string
- It returns the first
numelements ofarrOrStr.
R.take(1, ['foo', 'bar']) // => ['foo']
R.take(2, 'foo') // => 'fo'
takeLast(num: number, arrOrStr: T[]|string): T[]|string
- It returns the last
numelements ofarrOrStr.
R.takeLast(1, ['foo', 'bar']) // => ['bar']
R.takeLast(2, 'foo') // => 'oo'
tap(fn: Function, input: T): T
- It applies function to input and pass the input back. Use case is debuging in the middle of
R.compose.
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
- Determines whether
strmatchesregExpression
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'
toPairs(obj: object): any[]
It transforms an object to a list.
const list = {
a : 1,
b : 2,
c : [ 3, 4 ],
}
const expected = [ [ 'a', 1 ], [ 'b', 2 ], [ 'c', [ 3, 4 ] ] ]
const result = R.toPairs(list)
// expected === result
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:
> add.js
Rambda.add x 72,564,688 ops/sec ±4.81% (73 runs sampled)
Ramda.add x 56,396,341 ops/sec ±4.23% (82 runs sampled)
Lodash.add x 35,946,727 ops/sec ±1.50% (87 runs sampled)
> adjust.js
Rambda.adjust x 7,035,757 ops/sec ±0.96% (92 runs sampled)
Ramda.adjust x 11,520,117 ops/sec ±1.33% (91 runs sampled)
> any.js
Rambda.any x 57,187,584 ops/sec ±3.01% (85 runs sampled)
Ramda.any x 10,380,996 ops/sec ±3.85% (82 runs sampled)
Lodash.some x 36,716,897 ops/sec ±3.95% (77 runs sampled)
> append.js
Rambda.append x 3,499,777 ops/sec ±3.18% (82 runs sampled)
Ramda.append x 2,964,099 ops/sec ±0.87% (93 runs sampled)
> assoc.js
Rambda.assoc x 4,002,722 ops/sec ±1.03% (91 runs sampled)
Ramda.assoc x 6,014,560 ops/sec ±1.20% (92 runs sampled)
Lodash.set x 14,148,999 ops/sec ±1.23% (88 runs sampled)
> clone.js
Rambda.clone x 495,003 ops/sec ±22.29% (58 runs sampled)
Ramda.clone x 60,313 ops/sec ±14.66% (54 runs sampled)
Lodash.cloneDeep x 370,928 ops/sec ±3.22% (82 runs sampled)
> compose.js
Rambda.compose x 6,565,224 ops/sec ±6.65% (74 runs sampled)
Ramda.compose x 482,147 ops/sec ±7.44% (71 runs sampled)
Lodash.flowRight x 1,907,860 ops/sec ±4.24% (80 runs sampled)
> contains.js
Rambda.contains x 38,642,695 ops/sec ±6.33% (67 runs sampled)
Ramda.contains x 9,979,350 ops/sec ±24.61% (47 runs sampled)
Lodash.includes x 30,027,499 ops/sec ±1.73% (86 runs sampled)
> defaultTo.js
Rambda.defaultTo simple x 51,090,366 ops/sec ±2.84% (81 runs sampled)
Ramda.defaultTo x 29,850,625 ops/sec ±4.67% (74 runs sampled)
Rambda.defaultTo (when several arguments) x 10,753,835 ops/sec ±10.84% (58 runs sampled)
> drop.js
Rambda.drop x 7,355,396 ops/sec ±12.03% (62 runs sampled)
Ramda.drop x 1,278,065 ops/sec ±5.91% (74 runs sampled)
> dropLast.js
Rambda.dropLast x 7,620,630 ops/sec ±8.58% (64 runs sampled)
Ramda.dropLast x 1,131,885 ops/sec ±4.18% (80 runs sampled)
> endsWith.js
Rambda.endsWith x 28,003,665 ops/sec ±5.59% (77 runs sampled)
Ramda.endsWith x 656,403 ops/sec ±6.09% (81 runs sampled)
> equals.js
Rambda.equals x 1,085,925 ops/sec ±5.85% (75 runs sampled)
Ramda.equals x 123,968 ops/sec ±5.05% (80 runs sampled)
Lodash.isEqual x 356,517 ops/sec ±5.28% (81 runs sampled)
> filter.js
Rambda.filter x 15,054,483 ops/sec ±5.32% (74 runs sampled)
Ramda.filter x 4,411,613 ops/sec ±5.60% (76 runs sampled)
Lodash.filter x 12,980,591 ops/sec ±3.44% (77 runs sampled)
> find.js
Rambda.find x 14,086,382 ops/sec ±7.00% (76 runs sampled)
Ramda.find x 6,968,369 ops/sec ±4.86% (76 runs sampled)
Lodash.find x 8,130,806 ops/sec ±13.27% (63 runs sampled)
> findIndex.js
Rambda.findIndex x 48,179,679 ops/sec ±8.31% (71 runs sampled)
Ramda.findIndex x 2,561,304 ops/sec ±17.39% (33 runs sampled)
Lodash.findIndex x 3,636,170 ops/sec ±11.57% (54 runs sampled)
> flatten.js
Rambda.flatten x 3,651,487 ops/sec ±12.96% (57 runs sampled)
Ramda.flatten x 585,856 ops/sec ±0.39% (90 runs sampled)
Lodash.flatten x 12,330,106 ops/sec ±1.48% (93 runs sampled)
> head.js
Rambda.head x 73,327,652 ops/sec ±3.95% (77 runs sampled)
Ramda.head x 4,281,233 ops/sec ±2.27% (87 runs sampled)
Lodash.head x 67,943,467 ops/sec ±3.43% (77 runs sampled)
> headString.js
Rambda.head (when string) x 75,729,481 ops/sec ±3.76% (78 runs sampled)
Ramda.head (when string) x 4,215,626 ops/sec ±2.33% (84 runs sampled)
> identical.js
Rambda.identical x 68,465,698 ops/sec ±4.76% (74 runs sampled)
Ramda.identical x 19,430,040 ops/sec ±2.18% (82 runs sampled)
> indexOf.js
Rambda.indexOf x 52,087,884 ops/sec ±2.80% (78 runs sampled)
Ramda.indexOf x 23,475,389 ops/sec ±2.57% (83 runs sampled)
Lodash.indexOf x 50,416,017 ops/sec ±4.27% (79 runs sampled)
> init.js
Rambda.init x 33,425,823 ops/sec ±3.40% (78 runs sampled)
Ramda.init x 2,732,046 ops/sec ±12.71% (69 runs sampled)
Lodash.initial x 32,728,924 ops/sec ±4.09% (78 runs sampled)
> initString.js
Rambda.init (when string) x 71,090,037 ops/sec ±3.79% (74 runs sampled)
Ramda.init (when string) x 1,849,154 ops/sec ±7.90% (69 runs sampled)
> isEmpty.js
Rambda.isEmpty x 16,658,518 ops/sec ±8.41% (69 runs sampled)
Ramda.isEmpty x 100,014 ops/sec ±6.48% (75 runs sampled)
Lodash.isEmpty x 972,958 ops/sec ±5.22% (79 runs sampled)
> last.js
Rambda.last x 66,518,805 ops/sec ±5.77% (69 runs sampled)
Ramda.last x 4,065,920 ops/sec ±2.83% (84 runs sampled)
Lodash.last x 64,817,997 ops/sec ±6.13% (73 runs sampled)
> map.js
Rambda.map x 29,936,120 ops/sec ±3.21% (76 runs sampled)
Ramda.map x 6,112,792 ops/sec ±2.47% (88 runs sampled)
Lodash.map x 28,685,845 ops/sec ±1.63% (90 runs sampled)
> match.js
Rambda.match x 4,646,951 ops/sec ±1.00% (92 runs sampled)
Ramda.match x 1,990,270 ops/sec ±2.17% (90 runs sampled)
> mathMod.js
Rambda.mathMod x 31,132,727 ops/sec ±1.99% (89 runs sampled)
Ramda.mathMod x 15,986,746 ops/sec ±2.21% (86 runs sampled)
> mean.js
Rambda.mean x 54,726,189 ops/sec ±2.68% (85 runs sampled)
Ramda.mean x 1,167,399 ops/sec ±0.63% (91 runs sampled)
> median.js
Rambda.median x 2,416,103 ops/sec ±1.19% (93 runs sampled)
Ramda.median x 688,465 ops/sec ±1.07% (89 runs sampled)
> merge.js
Rambda.merge x 9,303,698 ops/sec ±2.12% (88 runs sampled)
Ramda.merge x 6,342,019 ops/sec ±2.58% (87 runs sampled)
Lodash.merge x 3,443,832 ops/sec ±1.93% (88 runs sampled)
> negate.js
Rambda.negate x 76,127,966 ops/sec ±4.33% (79 runs sampled)
Ramda.negate x 5,251,317 ops/sec ±2.66% (87 runs sampled)
> omit.js
Rambda.omit x 16,556,936 ops/sec ±1.28% (88 runs sampled)
Ramda.omit x 4,935,868 ops/sec ±2.58% (86 runs sampled)
Lodash.omit x 461,559 ops/sec ±1.06% (82 runs sampled)
> path.js
Rambda.path x 21,030,510 ops/sec ±1.80% (88 runs sampled)
Ramda.path x 12,366,254 ops/sec ±1.88% (89 runs sampled)
Lodash.get x 22,054,744 ops/sec ±1.31% (92 runs sampled)
> pathOr.js
Rambda.pathOr x 5,662,819 ops/sec ±4.74% (79 runs sampled)
Ramda.pathOr x 5,571,989 ops/sec ±1.72% (85 runs sampled)
> pick.js
Rambda.pick x 9,939,191 ops/sec ±1.69% (88 runs sampled)
Ramda.pick x 2,715,845 ops/sec ±2.35% (90 runs sampled)
Lodash.pick x 1,062,961 ops/sec ±2.56% (83 runs sampled)
> pipe.js
Rambda.pipe x 4,508,406 ops/sec ±2.65% (85 runs sampled)
Ramda.pipe x 757,113 ops/sec ±1.62% (86 runs sampled)
Lodash.flow x 2,318,846 ops/sec ±0.98% (91 runs sampled)
> product.js
Rambda.product x 8,924,477 ops/sec ±0.75% (91 runs sampled)
Ramda.product x 1,364,863 ops/sec ±0.39% (89 runs sampled)
> prop.js
Rambda.prop x 23,457,990 ops/sec ±1.24% (90 runs sampled)
Ramda.prop x 2,736,492 ops/sec ±0.62% (90 runs sampled)
> propEq.js
Rambda.propEq x 14,389,769 ops/sec ±1.34% (89 runs sampled)
Ramda.propEq x 2,673,442 ops/sec ±0.59% (89 runs sampled)
> propIs.js
Rambda.propIs x 26,337,209 ops/sec ±2.17% (85 runs sampled)
Ramda.propIs x 8,519,778 ops/sec ±2.74% (86 runs sampled)
> propOr.js
Rambda.propOr x 49,257,830 ops/sec ±3.43% (75 runs sampled)
Ramda.propOr x 3,907,852 ops/sec ±2.01% (88 runs sampled)
> range.js
Rambda.range x 14,450,269 ops/sec ±2.21% (84 runs sampled)
Ramda.range x 7,354,755 ops/sec ±2.44% (85 runs sampled)
Lodash.range x 10,475,753 ops/sec ±1.81% (89 runs sampled)
> reduce.js
Rambda.reduce x 9,262,518 ops/sec ±2.69% (88 runs sampled)
Ramda x 2,524,600 ops/sec ±1.24% (88 runs sampled)
Lodash x 13,553,365 ops/sec ±0.98% (88 runs sampled)
import omit from 'rambda/lib/omit'
Latest version that has this feature is
2.3.1
-
2.14.0 Add
R.groupWithby @selfrefactor | AddR.propOr,R.mathMod,R.mean,R.median,R.negate,R.productby @ku8ar -
2.12.0 Add
R.propIs- PR #213 and addR.sum- issue #207 -
2.11.2 Close Rambdax issue #32 - wrong
R.typewhen function is input -
2.11.1 Approve PR #182 - Changed typings to allow object as input to
R.forEachandR.map -
2.11.0 Approve PR #179 -
R.adjusthandles negative index;R.alldoesn't needR.filter -
2.10.2 Close issue #175 - missing typescript file
-
2.10.0 Approve huge and important PR #171 submitted by @helmuthdu - Add comments to each method, improve Typescript support
-
2.9.0
R.toPairsandR.fromPairs -
2.8.0 Approve PR #165
R.clone -
2.7.1 expose
src| Discussed at issue #147 -
2.7.0 Approve PR #161
R.isEmpty -
2.6.0
R.map,R.filterandR.forEachpass original object to iterator as third argument | Discussed at issue #147 -
2.5.0 Close issue #149 Add
R.partial|R.typehandlesNaN -
2.4.0 Major bump of
Rollup; Stop building for ES5 -
2.3.1 Close issue #90 | Add string type of path in
R.pathOr -
2.3.0 Close issue #89 | Fix missing
NumberTS definition inR.type -
2.2.0
R.defaultToaccepts indefinite number of input arguments. So the following is valid expression:const x = defaultTo('foo',null, null, 'bar') -
2.1.0 Restore
R.zipusing WatermelonDB implementation. -
2.0.0 Major version caused by removing of
R.zipandR.addIndex. Issue #85 rightfully finds that the implementation ofR.addIndexis not correct. This led to removing this method and also ofR.zipas it had depended on it. The second change is thatR.map,R.filterare passing array index as second argument when looping over arrays. The third change is thatR.includeswill returnfalseif input is neigherstringnorarray. 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
srcfolder instead ofmodules -
1.2.5 Fix
omittyping -
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 passingundefinedtoR.mapandR.mergeissue #77 -
1.2.0 Add
R.min,R.minBy,R.max,R.maxBy,R.nthandR.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.composeaccepts 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.mapandR.filterpass 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.pipetypings -
1.0.3
R.ifElseaccept also boolean as condition argument -
1.0.2 Remove
typedDefaultToandtypedPathOr| AddR.pickAllandR.none -
1.0.0 Major change as build is now ES6 not ES5 compatible (Related to issue #46)| Making
Rambdafully tree-shakeable| Edit Typescript definition -
0.9.8 Revert to ES5 compatible build - issue #46
-
0.9.7 Refactor for
Rolluptree-shake | RemoveR.padEndandR.padStart -
0.9.6 Close issue #44 -
R.reversemutates the array -
0.9.5 Close issue #45 - invalid Typescript typings
-
0.9.4 Add
R.rejectandR.without(PR#41 PR#42) | Remove 'browser' field inpackage.jsondue to Webpack bug 4674 -
0.9.3 Add
R.forEachandR.times -
0.9.2 Add
Typescriptdefinitions -
0.9.1 Close issue #36 - move current behaviour of
defaultToto a new methodtypedDefaultTo; makedefaultTofollow Ramda spec; addpathOr; addtypedPathOr. -
0.9.0 Add
R.pipePR#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
WebpackwithRollup- PR29 -
0.8.6 Add
R.tapandR.identity -
0.8.5 Add
R.all,R.allPass,R.both,R.eitherandR.complement -
0.8.4 Learning to run
yarn testbeforeyarn publishthe hard way -
0.8.3 Add
R.always,R.TandR.F -
0.8.2 Add
concat,padStart,padEnd,lastIndexOf,toString,reverse,endsWithandstartsWithmethods -
0.8.1 Add
R.ifElse -
0.8.0 Add
R.not,R.includes| Take string as condition forR.pickandR.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 incorrectlyfunctionwhen called with more arguments -
0.7.3 Close issue #9 - Compile to
es2015; Approve PR #10 - addR.addIndexto the API -
0.7.2 Add
Promisesupport forR.type -
0.7.1 Close issue #7 - add
R.reduceto the API -
0.7.0 Close issue #5 - change name of
currytopartialCurry; add new methodcurry, which works just like Ramda'scurry -
0.6.2 Add separate documentation site via
docsify
Running benchmarks
- To run all benchmarks
yarn run benchmark all
- To run single or number of benchmarks
yarn run benchmark add compose filter
Projects using Rambda
Projects using Rambdax
Rambda in the wild
-
Trending in
Javascripting.comlist:
Links to Rambda