Extended version of Rambda(utility library) - Documentation
const R = require("rambdax")
const result = R.compose(
R.filter(val => val>2),
R.flatten,
)([ [1], [2], [3], 4])
console.log(result) // => [3, 4]
Simple yarn add rambdax
is sufficient
ES5 compatible version -
yarn add rambdax#0.8.0
Rambdax passthrough all Rambda methods and introduce some new functions.
The idea of Rambdax is to extend Rambda without worring for Ramda compatibility.
Rambdax
replacesRambda
'sis
with very different method. Check the API below for further details.
You will need at least version 3.0.0
for Rambdax
versions after 0.12.0
.
Methods between allFalse
and when
belong to Rambdax, while methods between add
and without
are inherited from Rambda.
Several methods are dropped between versions 0.24.0
and 1.0.0
. The older version of the API is located /files/deprecated/README.md
allFalse(...inputs: any|predicate[]): boolean
It returns true
if all passed elements return false
when passed to Boolean
.
If single input element is a function, then it will be evaluated.
R.allFalse(null, undefined, '', () => false)
//=> true
allTrue(...inputs: any|predicate[]): boolean
It returns true
if all passed elements return true
when passed to Boolean
.
If argument is function, it will be evaluated.
const x = 2
const result = R.allTrue([1,2], x > 1, {}, () => true)
//=> true
allType(targetType: string): (...inputs: any[]) => boolean
It returns a function, which will return true
if all passed elements has the same type as the targetType
. The example below explains it better:
const result = R.allType('String')('foo','bar','baz')
//=> true
anyFalse(...inputs: any|predicate[]): boolean
It returns true
if any of the passed elements returns false
when passed to Boolean
.
If argument is function, it will be evaluated.
R.anyFalse(1, {a:1}, 'foo', () => false)
//=> true
anyTrue(...inputs: any|predicate[]): boolean
It returns true
if any of the passed elements returns true
when passed to Boolean
.
If argument is function, it will be evaluated.
R.anyTrue(0, {}, '', () => true)
//=> true
anyType(targetType: string): (...inputs: any[]) => boolean
It returns a function, which will return true
if at least one of the passed elements has the same type as the targetType
. The example below explains it better:
R.anyType('String')(1, {},'baz')
//=> true
change(origin: object, path: string, changeData: any): object
It helps changing object's properties if there are below 3 levels deep.
Explanation:
path
provide way to specify which object's sub-branch you want to manipulate. Pass empty string if you target the whole origin
object.
changeData
can be a direct value. If it is a object, then this object is used to edit or add new properties to the selected sub-branch.
const simpleResult = change(
{ a: 1, b: { c: 2 } },
'b.c',
3
)
const expectedSimpleResult = {
a: 1,
b: { c: 3 }
}
// simpleResult === expectedSimpleResult
const origin = {
a : 0,
foo : {
bar : 1,
bax : { nested : 2 },
},
}
const changeData = {
bar: 2,
bay: 3,
bax: { baq: 9 }
}
const result = change(
origin,
'foo',
changeData
)
const expectedResult = {
a : 0,
foo : {
bar : 2,
bay : 3,
bax : {
nested : 2,
baq: 9
},
},
}
// result === expectedResult
composeAsync(...fns: Array<Function|Async>)(startValue: any): Promise
It is same as R.compose
but with support for asynchronous functions.
Note that it doesn't work with promises or function returning promises such as const foo = input => new Promise(...)
.
const fn = async x => {
await R.delay(500)
return x+1
}
const fnSecond = async x => fn(x)
const result = R.composeAsync(
fn,
fnSecond
)(0)
// `result` resolves to `2`
composed(...fnList: any[]): any
It is basically R.compose
but instead of passing the input argument as (input)
, you pass it as the last argument. It is easier to understand with the following example:
const result = composed(
R.map(x => x*10),
R.filter(x => x > 1),
[1,2,3]
)
// => [20, 30]
debounce(fn: Function, ms: number): any
Creates a debounced function that delays invoking fn
until after wait milliseconds ms
have elapsed since the last time the debounced function was invoked. (description is taken from Lodash
docs)
let counter = 0
const inc = () => {
counter++
}
const debouncedInc = R.debounce(inc, 900)
const result = async function(){
debouncedInc()
await R.delay(500)
debouncedInc()
await R.delay(800)
console.log(counter) //=> 0
await R.delay(1000)
console.log(counter) //=> 1
return counter
}
// `result` resolves to `1`
defaultToStrict(defaultValue: T, ...inputArguments: any[]): T
It either returns defaultValue
, if all of inputArguments
are considered falsy.
Or it returns the first truthy inputArguments
instance(from left to right).
It is similar to R.defaultTo
, but its definition for truthy value is different. The requirement in R.defaultTo
in any value different than undefined
, null
or NaN
. With R.defaultToStrict
the conditions are:
- Truthy with
Boolean
- Has the same type as
defaultValue
(according toR.type
) - It is neither empty object or empty array
R.defaultToStrict('foo', undefined) // => 'foo'
R.defaultToStrict('foo', 1) // => 'foo'
R.defaultToStrict('foo', {}) // => 'foo'
R.defaultTo('foo', undefined, 1, [], {}) // => 'foo'
R.defaultTo('foo', undefined, 1, [], {}, 'bar') // => 'bar'
defaultToWhen(fallback: any, fn: Function, ...inputArguments: any[]): any
It returns fallback
, if there is none instance of inputArguments
that satisfies the predicate fn
.
If there is such instance, then it will be the end result of R.defaultToWhen
.
const fn = x => x > 2
const fallback = 10
const result = R.defaultToWhen(fallback, fn, 1,6,8,0 )
// result is 6
delay(ms: number): Promise
setTimeout
as a promise that resolves to R.DELAY
variable.
The value of R.DELAY
is 'RAMBDAX_DELAY'
.
const result = R.delay(1000)
// `result` resolves to `'RAMBDAX_DELAY'`
findInObject(fn: Function, obj: object): object
It will return object with properties prop
and value
if predicate function returns true
for a pair of property and value within obj
.
If predicate cannot be satisfied, it returns {fallback: true}
.
const fn = (x, key) => x > 1 && key.length > 1
const obj = {
a : 1,
b : 2,
foo : 3,
}
const result = R.findInObject(fn, obj)
// => { prop : 'foo',value : 3}
setter(key: string|object, value?: any): void
It provides access to the cache object.
You either set individual key-value pairs with R.setter(key, value)
or you pass directly object, which will be merged with the cache object
R.setter({a: 1,b: 'bar'})
R.getter('b')
// => 'bar'
getter(key: undefined|string|string[]): any
It provides access to the cache object.
If undefined
is used as a key, this method will return the whole cache object.
If string
is passed, then it will return cache value for this key.
If array of string
is passed, then it assume that this is array of keys and it will return the corresponding cache values for these keys.
R.setter('foo','bar')
R.setter('a', 1)
R.getter(['foo','a'])
// => {foo:'baz', a:1}
reset(): void
It resets the cache object.
R.setter({a: 1,b: 'bar'})
R.getter('b') // => 'bar'
R.reset()
R.getter('b') // => undefined
glue(input: string, glueString?: string): string
It transforms multiline string to single line by gluing together the separate lines with the glueString
and removing the empty spaces. By default glueString
is equal to single space, so if that is what you need, then you can just pass a single argument.
const result = R.glue(`
foo
bar
baz
`)
const expectedResult = 'foo bar baz'
// result === expectedResult
hasPath(input: string|string[], input: object): boolean
It will return true, if input
object has truthy path
(calculated with R.path
).
const path = 'a.b'
const obj = {a: {b:[]}}
const result = hasPath(path,obj)
expect(result).toBe(true)
headObject(input: object): {prop: string, value: T}
It must be used with object that has only one key, i.e. {foo:1}
.
It is build for the use case, when we want to pass object and its name.
const foo = x => x + 2
const bar = x => x * 8
[{foo}, {bar}]
.map(method => {
const {prop, value: fn} = R.headObject(method)
console.log(prop, `result ${fn(1)}`)
})
includesType(targetType: string, list: any[]): boolean
It returns true
if any member of list
array has the same type as the targetType
.
const result = R.includesType(
'String',
[1,2,'foo']
)
// => true
inject(injection: string, marker: string, str: string, beforeFlag: boolean): string
const resultDefault = R.inject(
' INJECTION',
'MARKER',
'foo bar MARKER baz'
)
const expectedResultDefault = 'foo bar MARKER INJECTION baz'
const resultWithBeforeFlag = R.inject(
'INJECTION ',
'MARKER',
'foo bar MARKER baz',
true
)
const expectedResultWithBeforeFlag = 'foo bar INJECTION MARKER baz'
const result = [
resultDefault,
resultWithBeforeFlag
]
const expectedResult = [
expectedResultDefault,
expectedResultWithBeforeFlag
]
isAttach(): boolean
It attaches is
method to object-like variables. This is
method acts like R.pass
.
It returns true
when it is called initially and it returns false
for sequential calls.
R.isAttach()
const foo = [1,2,3]
const result = foo.is(['number'])
// => true
isFalsy(x: any): boolean
It returns true
if x
is falsy.
const result = R.map(
R.isFalsy
)([null, '', [], {}])
// => [ true, true, true, true ]
isFunction(x: any): boolean
It returns true
if type of x
is one among Promise
, Async
or Function
.
const result = R.isFunction(
x => x
)
// => true
isNil(x: any): boolean
It returns true
is x
is either null
or undefined
.
R.isNil(null) // => true
R.isNil(1) // => false
isPromise(x: any): boolean
It returns true if x
is either async function or unresolved promise.
R.isPromise(R.delay)
// => true
isType(xType: string, x: any): boolean
It returns true if x
matches the type returned from R.type
.
R.isType('Async',async () => {})
// => true
isValid({ input: object: schema: object }): boolean
It checks if input
is following schema
specifications.
If validation fails, it returns false
.
Please check the detailed explanation as it is hard to write a short description of this method.
Independently, somebody else came with very similar idea called superstruct
const result = R.isValid({
input:{ a: ['foo','bar'] },
schema: {a: ['string'] }
})
// => true
maybe(ifRule: Boolean, whenIf: T, whenElse: T): T
It acts as ternary operator and it is helpful when we have nested ternaries.
const x = 4
const y = 8
const result = R.maybe(
x > 2,
y > 10 ? 3 : 7,
5
)
// `result` is `7`
mapAsync(fn: Async|Promise, arr: Array): Promise
Sequential asynchronous mapping with fn
over members of arr
.
async function fn(x){
await R.delay(1000)
return x+1
}
const result = R.composeAsync(
R.mapAsync(fn),
R.map(x => x*2)
)( [1, 2, 3] )
// `result` resolves after 3 seconds to `[3, 5, 7]`
mapFastAsync(fn: Async|Promise, arr: Array): Promise
Parrallel asynchronous mapping with fn
over members of arr
.
async function fn(x){
await R.delay(1000)
return x+1
}
const result = R.composeAsync(
R.mapAsync(fn),
R.map(x => x*2)
)( [1, 2, 3] )
// `result` resolves after 1 second to `[3, 5, 7]`
memoize(fn: Function|Promise): any
When fn
is called for a second time with the same input, then the cache result is returned instead of calling fn
.
let counter = 0
const fn = (a,b) =>{
counter++
return a+b
}
const memoized = R.memoize(fn)
memoized(1,2)
memoized(1,2)
console.log(counter) //=> 1
mergeAll(input: Object[]): Object
It merges all objects of input
array sequentially and returns the result.
const arr = [
{a:1},
{b:2},
{c:3}
]
const expectedResult = {
a:1,
b:2,
c:3
}
const result = R.mergeAll(arr)
// result === expectedResult
mergeDeep(slave: object, master: object): object
It is best explained with the test example:
const slave = {
name: 'evilMe',
age: 10,
contact: {
a: 1,
email: '[email protected]'
}
}
const master = {
age: 40,
contact: { email: '[email protected]' },
}
const result = mergeDeep(slave,master)
const expected = {
"age": 40,
"name": "evilMe",
"contact": {
"a": 1,
"email": "[email protected]"
},
}
expect(result).toEqual(expected)
mergeRight(master: object, slave:object)
Same as R.merge
but in opposite direction.
nextIndex(index: number, list: any[]): number
It returns the next index of the list, i.e. it increments unless we have reached the end of the list(in this case 0
is returned).
ok(...inputs: any[]): (schemas: any[]) => true | Error
It checks if inputs
are following schemas
specifications.
It uses underneath R.isValid.
If validation fails, it throws. If you don't want that, then you can use R.is
. It is the same as R.ok
method, but it returns false
upon failed validation.
const result = R.ok(
1, [ 'foo', 'bar' ]
)('number', [ 'string' ])
// => true
once(fn: Function): Function
It returns a function, which invokes only oncefn
.
const addOneOnce = R.once((a, b, c) => a + b + c)
console.log(addOneOnce(10, 20, 30)) //=> 60
console.log(addOneOnce(1, 2, 3)) //=> 60
opposite(fn: Function): Function
Same as R.complement
otherwise(fallback: Function, toResolve: Promise): Promise
It is meant to be used inside pipe or compose methods. It allows to catch the error inside the incoming promise and perform fallback
in case of error. If no error occurs, it will act as identity, i.e. pass the input as a result.
test('with promise', async () => {
const fetch = x =>
new Promise((res, rej) => rej(new Error('FOO_ERROR')))
const getMemberName = pipe(
email => ({ query : email }),
fetch,
R.otherwise(e => {
expect(e.message).toBe('FOO_ERROR')
return { firstName : 'BAR' }
}),
R.then(R.pick('firstName,lastName'))
)
const result = await getMemberName('FOO')
expect(result).toEqual({ firstName : 'BAR' })
})
pathEq(path:string|string[], target: any, obj: object): boolean
const result = R.pathEq(
'a.b',
1,
{a: {b:1} }
)
// => true
pass(...inputs: any[]): (schemas: any[]) => boolean
It checks if inputs
are following schemas
specifications.
It uses underneath R.isValid
If validation fails, it returns false
.
const result = R.pass(1,['foo','bar'])('number',['string'])
// => true
partition(predicate: Function, input: Array|Object): [Array|Object, Array|Object]
It is similar to R.filter
but it will return also the instances that are not passing the predicate function.
It works also with object as input. Please check the example below:
import { partition } from 'rambdax'
test('with object', () => {
const predicate = (value, prop) => {
expect(
typeof prop
).toBe('string')
return value > 2
}
const input = {
a : 1,
b : 2,
c : 3,
d : 4,
}
const result = partition(predicate, input)
const expectedResult = [
{
c : 3,
d : 4,
},
{
a : 1,
b : 2,
},
]
expect(
result
).toEqual(expectedResult)
})
test('with array', () =>{
const rule = (x, i) => {
expect(
typeof i
).toBe('number')
return x > 2
}
const list = [1,2,3,4]
const result = partition(rule,list)
const expectedResult = [[3,4], [1,2]]
expect(
result
).toEqual(expectedResult)
})
piped(...fnList: any[]): any
It is basically R.pipe
but instead of passing the input argument as (input)
, you pass it as the first argument. It is easier to understand with the following example:
const result = piped(
[1,2,3],
R.filter(x => x > 1),
R.map(x => x*10),
)
// => [20, 30]
pipedAsync(input: any, ...fns: Array<Function|Async>): Promise
It accepts input as first argument and series of functions as next arguments. It is same as R.pipe
but with support for asynchronous functions.
Also functions that returns Promise
will be handled as regular function not asynchronous. Such example is const foo = input => new Promise(...)
.
const result = await pipedAsync(
100,
async x => {
await delay(100)
return x + 2
},
add(2),
async x => {
const delayed = await delay(100)
return delayed + x
}
)
const expected = 'RAMBDAX_DELAY104'
// result === expected
produce(conditions: Object, input: any): Promise|Object
It is very similar to Ramda's 'applySpec' method
const conditions = {
foo: a => a > 10,
bar: a => ({baz:a})
}
const result = R.produce(conditions, 7)
const expectedResult = {
foo: false,
bar: {baz: 7}
}
// result === expectedResult
conditions
is an object with sync or async functions as values.
The values of the returned object returnValue
are the results of those functions when input
is passed.
The properties of the returned object are equal to input
.
If any of the conditions
is a Promise
, then the returned value is a Promise
that resolves to returnValue
.
promiseAllObject(promises: Object): Promise
It acts as Promise.all
for object with Promises.
It returns a promise that resolve to object.
const fn = ms => new Promise(resolve => {
setTimeout(() => {
resolve(ms)
}, ms)
})
const promises = {
a : fn(1),
b : fn(2),
}
const result = R.promiseAllObject(promises)
const expectedResult = { a:1, b:2 }
// `result` resolves to `expectedResult`
random(min: number, max: number): number
It returns a random number between min
inclusive and max
inclusive.
remove(inputs: string|RegExp[], text: string): string
It will remove all inputs from text
sequentially.
const result = remove(
['foo','bar'],
'foo bar baz foo'
)
// => 'baz foo'
renameProps(rules: Object, input: Object): Object
If property prop
of rules
is also a property in input
, then rename input
property to rules[prop]
.
const rules = {
f: "foo",
b: "bar"
}
const input = {
f:1,
b:2
}
const result = R.renameProps(rules, input)
const expectedResult = {
foo:1,
bar:2
}
// result === expectedResult
resolve(afterResolve: Function, toResolve: Promise): Promise
Its purpose is to be used with pipe or compose methods in order to turn the composition to asynchronous.
The example should explain it better:
const expected = {
firstName : 'FIRST_NAME_FOO',
lastName : 'LAST_NAME_FOO',
}
const fetchMember = async x => {
await R.delay(200)
return {
a : 1,
firstName : `FIRST_NAME_${ x.query }`,
lastName : `LAST_NAME_${ x.query }`,
}
}
const getMemberName = pipe(
email => ({ query : email }),
fetchMember,
resolve(pick('firstName,lastName'))
)
const result = await getMemberName('FOO')
// result === expected
s(): undefined
Taken from https://github.com/staltz/zii
Chain function calls using a prototype function s
// To turn it on
R.s()
// Then
const result = 'foo'
.s(R.toUpper)
.s(R.take(2))
.s(R.add('bar'))
const expectedResult = 'barFO'
// result === expectedResult
shuffle(arr: T[]): T[]
It returns randomized copy of array.
Edited fork of Switchem library.
It is best explained with the following example:
const valueToMatch = {foo: 1}
const result = R.switcher(valueToMatch)
.is('baz', 'is baz')
.is( x => typeof x === 'boolean', 'is boolean')
.is({foo: 1}, 'Property foo is 1')
.default('is bar')
console.log(result) // => 'Property foo is 1'
As you can see valueToMatch
is matched sequentially against various is
conditions.
If none of them is appliable, then default
value is returned as result.
Note that default
must be the last condition and it is mandatory.
Rambda's equals
is used as part of the comparison process.
tapAsync(fn: Function|Async|Promise, inputArgument: T): T
It is R.tap
that accept promise-like fn
argument.
let counter = 0
const inc = () => {
counter++
}
const throttledInc = R.throttle(inc, 800)
const replWrap = async x => {
throttledInc()
await R.delay(500)
throttledInc()
const a = await R.delay(1000)
console.log(counter)
}
const result = R.tapAsync(replWrap, "foo")
// the console logs `foo`
// `result` is equal to 'foo'
template(input: string, templateInput: object): string
It generages a new string from input
by replacing all {{foo}}
occurances with values provided by `templateInput.
const input = 'foo is {{bar}} even {{a}} more'
const templateInput = {"bar":"BAR", a: 1}
const result = R.template(input,templateInput)
const expectedResult = 'foo is BAR even 1 more'
// result === expectedResult
toDecimal(num: number, charsAfterDecimalPoint: number): number
R.toDecimal(2.45464,2) // => 2.45
throttle(fn: Function, period: number): Function
It creates a throttled function that invokes fn
maximum once for a period
of milliseconds.
let counter = 0
const inc = () => {
counter++
}
const throttledInc = R.throttle(inc, 800)
const result = async () => {
throttledInc()
await R.delay(500)
throttledInc()
return counter
}
// `result` resolves to `1`
tryCatch(fn: Async|Function, fallback: any): Function
It returns function that runs fn
in try/catch
block. If there was an error, then fallback
is used to return the result. Note that fn
can be value, function or promise-like.
Please check the tests below in order to fully understand this method, as it doesn't match the behaviour of the same method in Ramda
.
import { delay } from './delay'
import { prop } from './rambda/prop'
import { tryCatch } from './tryCatch'
test('throws when fn is not function', () => {
const fn = 'foo'
expect(
() => tryCatch(fn, false)(null)
).toThrow(`R.tryCatch | fn 'foo'`)
})
test('when fallback is used', () => {
const fn = prop('x')
expect(tryCatch(fn, false)(null)).toBe(false)
})
test('when fallback is function', () => {
const fn = prop('x')
expect(tryCatch(fn, x => x)(null)).toBe(null)
})
test('when fn is used', () => {
const fn = prop('x')
expect(tryCatch(fn, false)({})).toBe(undefined)
expect(tryCatch(fn, false)({ x: 1 })).toBe(1)
})
test('when async + fallback', async () => {
let called = false
const fn = async input => {
await delay(input)
called = true
return JSON.parse('{a:')
}
expect(await tryCatch(fn, 'fallback')(100)).toBe('fallback')
expect(called).toBe(true)
})
test('when async + fallback is function', async () => {
let called = false
const fn = async input => {
await delay(input)
called = true
return JSON.parse('{a:')
}
expect(await tryCatch(fn, x => x + 1)(100)).toBe(101)
expect(called).toBe(true)
})
test('when async + fallback is async', async () => {
let called = false
const fn = async input => {
await delay(input)
called = true
return JSON.parse('{a:')
}
const fallback = async input => {
return input + 1
}
expect(await tryCatch(fn, fallback)(100)).toBe(101)
expect(called).toBe(true)
})
test('when async + fn', async () => {
let called = false
const fn = async input => {
await delay(input)
called = true
return input + 1
}
expect(await tryCatch(fn, 'fallback')(100)).toBe(101)
expect(called).toBe(true)
})
unless(rule: Function|boolean, whenFalse: Function|any): Function
The method returns function that will be called with argument input
.
If rule
with input
as argument returns false, then the end result will be the outcome of whenFalse
function with input
as argument. In the other case, the final output will be the input
itself.
Please note that unlike Ramda's unless
, this method accept also plain values as rule
(boolean values) and whenFalse
(any values) arguments.
const result = R.unless(
R.isNil,
R.inc
)(1)
// => 2
wait(fn: Async): Promise<[any, Error]>
It provides Golang
-like interface for handling promises.
void async function wait(){
const [result, err] = await R.wait(R.delay(1000))
// => err is undefined
// => result is `RAMBDAX_DELAY`
}()
waitFor(condition: any, ms: number): Promise
It returns true
, if condition
returns true
within ms
milisececonds time period.
Best description of this method are the actual tests:
import { waitFor } from './waitFor'
const howLong = 1000
test('true', async () => {
let counter = 0
const condition = x => {
counter++
return counter > x
}
const result = await waitFor(condition, howLong)(6)
expect(result).toEqual(true)
})
test('false', async () => {
let counter = 0
const condition = x => {
counter++
return counter > x
}
const result = await waitFor(condition, howLong)(12)
expect(result).toEqual(false)
})
test('async condition | true', async () => {
let counter = 0
const condition = async x => {
counter++
return counter > x
}
const result = await waitFor(condition, howLong)(6)
expect(result).toEqual(true)
})
test('async condition | false', async () => {
let counter = 0
const condition = async x => {
counter++
return counter > x
}
const result = await waitFor(condition, howLong)(12)
expect(result).toEqual(false)
})
test('throws when fn is not function', () => {
const fn = 'foo'
expect(() => waitFor(fn, howLong)()).toThrow('R.waitFor')
})
where(conditions: object, input: object): boolean
Each property prop
in conditions
is a function.
This function is called with input(prop)
. If all such function calls return true
, then the final result is also true
.
const condition = R.where({
a : aProp => typeof aProp === "string",
b : bProp => bProp === 4
})
const result = condition({
a : "foo",
b : 4,
c : 11,
}) //=> true
whereEq(rule: object, input: any): boolean
It will return true
if all of input
object fully or partially include rule
object.
The definition for input
is any
as the method perform type check on it and if it is not an object, it will return false
. Note that Ramda will throw in this case.
const rule = { a : { b : 1 } }
const input = {
a : { b : 1 },
c : 2,
}
const result = whereEq(rule, input)
//=> true
when(rule: Function|boolean, whenTrue: Function|any): Function
Note that unlike Ramda's when
, this method accept values as whenTrue
argument.
const truncate = R.when(
x => x.length > 5,
R.compose(x => `${x}...`, R.take(5))
)
const result = truncate('12345678')
// => '12345...'
whenAsync(rule: condition: Async | Function | boolean, whenFn: Async | Function): Promise
const replWrap = async input => {
const wrapResult = await R.whenAsync(
async x => {
await R.delay(x*100)
return x > 2
},
async x => {
await R.delay(x*100)
return x * 5
}
)(input)
return wrapResult
}
const result = replWrap(5)
// => 25
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'
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
true
ifobj
has 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
includes(valueToFind: T|string, input: T[]|string): boolean
If input
is string, then this method work as native includes
.
If input
is array, then R.equals
is used to define if valueToFind
belongs to the list.
R.includes('oo', 'foo') // => true
R.includes({a: 1}, [{a: 1}]) // => true
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('') // => true
R.isEmpty({ x : 0 }) // => 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
- 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
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
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]
slice(list: T[], from: Number, to: Number)
Returns the elements of the given list or string (or object with a slice
method) from fromIndex
(inclusive) to toIndex
(exclusive).
Dispatches to the slice
method of the third argument, if present.
R.slice(1, 3, ['a', 'b', 'c', 'd'])
//=> ['b', 'c']
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
arrOrStr
into 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
num
elements ofarrOrStr
.
R.take(1, ['foo', 'bar']) // => ['foo']
R.take(2, 'foo') // => 'fo'
takeLast(num: number, arrOrStr: T[]|string): T[]|string
- It returns the last
num
elements 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
str
matchesregExpression
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}