remeda中文文档
[TOC]
一.简介
- 出现原因:没有好的实用程序库可以很好地与 TypeScript 配合使用。使用 Lodash 或 Ramda 时,有时必须手动注释类型。Remeda 是用 TypeScript 编写和测试的, 意味着用户不需要自定义类型。如果是ts应用,优先推荐该库
- 当前版本:v1.2.0
- 把英文官网api文档全部整理翻译过来的,如遇问题,可联系译者邮箱:1311140141@qq.com
二.说明
- remeda的方法均不会改变传入的数据,只会返回新的数据。(不会产生副作用)
- 如下所示,大多数的remeda方法都有两种用法,数据在前和数据在后。后面文档参数部分均按数据在前的方式写。数据在后的方式自己推断
R.pick(obj, ['firstName', 'lastName']); // 数据在前 推荐
R.pipe(obj, R.pick(['firstName', 'lastName'])); // 数据在后
R.pick(['firstName', 'lastName'], obj); // 错误用法,无法工作
R.pick(['firstName', 'lastName'])(obj); // 这是数据在后,可以工作,但类型无法推断
- 当使用
pipe方法时,许多方法都支持惰性求值。文档中会以[p]标识。
// Get first 3 unique values
const arr = [1, 2, 2, 3, 3, 4, 5, 6];
const result = R.pipe(
arr, // only four iterations instead of eight (array.length)
R.map(x => {
console.log('iterate', x);
return x;
}),
R.unique(),
R.take(3)
); // => [1, 2, 3]
/**
* Console output:
* iterate 1
* iterate 2
* iterate 2
* iterate 3
* /
- 可迭代函数都有一个额外的
indexed属性, 和(element, index, array)的许多方法相似. 文档中以[i]标识
const arr = [10, 12, 13, 3];
// filter even values
R.filter(arr, x => x % 2 === 0); // => [10, 12]
// filter even indexes
R.filter.indexed(arr, (x, i, array) => i % 2 === 0); // => [10, 13]
方法名简介
描述
用法:
数据在前用法数据在后用法
参数:
参数名(参数类型): 参数描述
返回:
(
返回类型): 返回描述
例子:
// 实例代码
三.Number
[clamp限制值范围]
将给定值限制在最小和最大范围内。
用法:
R.clamp(value, { [min], [max] })R.clamp({ [min], [max] })(value)
参数:
value(Number): 需要限制的对象[min](Number): 限制的最小值[max](Number): 限制的最大值
返回:
(
Number): 返回经过限制处理后的值
例子:
clamp(10, { min: 20 }) // => 20
clamp(10, { max: 5 }) // => 5
clamp(10, { max: 20, min: 5 }) // => 10
clamp({ min: 20 })(10) // => 20
clamp({ max: 5 })(10) // => 5
clamp({ max: 20, min: 5 })(10) // => 10
[add两值相加]
用法:
R.add(value, addend);R.add(addend)(value);
例子:
R.add(10, 5); // => 15
R.add(10, -5); // => 5
R.reduce([1, 2, 3, 4], R.add, 0); // => 10
R.add(5)(10); // => 15
R.add(-5)(10); // => 5
R.map([1, 2, 3, 4], R.add(1)); // => [2, 3, 4, 5]
[subtract两值相减]
用法:
R.subtract(value, subtrahend);R.subtract(subtrahend)(value);
例子:
R.subtract(10, 5); // => 5
R.subtract(10, -5); // => 15
R.reduce([1, 2, 3, 4], R.subtract, 20); // => 10
R.subtract(5)(10); // => 5
R.subtract(-5)(10); // => 15
R.map([1, 2, 3, 4], R.subtract(1)); // => [0, 1, 2, 3]
[multiply两值相乘]
用法:
R.multiply(value, multiplicand);R.multiply(multiplicand)(value);
例子:
R.multiply(3, 4); // => 12
R.reduce([1, 2, 3, 4], R.multiply, 1); // => 24
R.multiply(4)(3); // => 12
R.map([1, 2, 3, 4], R.multiply(2)); // => [2, 4, 6, 8]
[divide两值相除]
用法:
R.divide(value, divisor);R.divide(divisor)(value);
例子:
R.divide(12, 3); // => 4
R.reduce([1, 2, 3, 4], R.divide, 24); // => 1
R.divide(3)(12); // => 4
R.map([2, 4, 6, 8], R.divide(2)); // => [1, 2, 3, 4]
[sumnumber数组累加]
空数组返回0
用法:
R.sum(data);R.sum()(data);
例子:
R.sum([1, 2, 3]); // => 6
R.sum([]); // => 0
R.pipe([1, 2, 3], R.sum()); // => 6
R.pipe([], R.sum()); // => 0
[productnumber数组累乘]
空数组返回0
用法:
R.product(data);R.product()(data);
例子:
R.product([1, 2, 3]); // => 6
R.product([]); // => 0
R.pipe([1, 2, 3], R.product()); // => 6
R.pipe([], R.product()); // => 0
[ceil向上取整到指定的小数位]
可以给负值
用法:
R.ceil(value, precision);R.ceil(precision)(value);
例子:
R.ceil(123.9876, 3); // => 123.988
R.ceil(483.22243, 1); // => 483.3
R.ceil(8541, -1); // => 8550
R.ceil(456789, -3); // => 457000
R.ceil(3)(123.9876); // => 123.988
R.ceil(1)(483.22243); // => 483.3
R.ceil(-1)(8541); // => 8550
R.ceil(-3)(456789); // => 457000
[floor向下取整到指定的小数位]
可以给负值
用法:
R.floor(value, precision);R.floor(precision)(value);
例子:
R.floor(123.9876, 3); // => 123.987
R.floor(483.22243, 1); // => 483.2
R.floor(8541, -1); // => 8540
R.floor(456789, -3); // => 456000
R.floor(3)(123.9876); // => 123.987
R.floor(1)(483.22243); // => 483.2
R.floor(-1)(8541); // => 8540
R.floor(-3)(456789); // => 456000
[round四舍五入到指定的小数位]
可以给负值
用法:
R.round(value, precision);R.round(precision)(value);
例子:
R.round(123.9876, 3); // => 123.988
R.round(483.22243, 1); // => 483.2
R.round(8541, -1); // => 8540
R.round(456789, -3); // => 457000
R.round(3)(123.9876); // => 123.988
R.round(1)(483.22243); // => 483.2
R.round(-1)(8541); // => 8540
R.round(-3)(456789); // => 457000
四.String
[randomString获取随机字符串]
从a-zA-Z0-9中生成一个固定长度的随机字符串
用法:
randomString(length)
例子:
randomString(5) // => aB92J
[sliceString截取字符串]
String.prototype.slice 的数据在后版本
用法:
R.sliceString(indexStart)(string); / R.sliceString(indexStart, indexEnd)(string);
例子:
R.sliceString(1)(`abcdefghijkl`); // => `bcdefghijkl`
R.sliceString(4, 7)(`abcdefghijkl`); // => `efg`
五.Object
[addProp给对象新增属性]
用法:
R.addProp(obj, prop, value)R.addProp(prop, value)(obj)
参数:
obj(Object) 目标对象prop(String) 要添加的key名称value(any) 要添加的key对应的值
返回:
(
Object): 返回新的对象
例子:
R.addProp({ firstName: 'john' }, 'lastName', 'doe') // => {firstName: 'john', lastName: 'doe'}
R.addProp('lastName', 'doe')({ firstName: 'john' }) // => {firstName: 'john', lastName: 'doe'}
[omit删除指定键]
返回原对象删除指定键后的新对象
用法:
R.omit(obj, names)R.omit(names)(obj)
例子:
R.omit({ a: 1, b: 2, c: 3, d: 4 }, ['a', 'd']) // => { b: 2, c: 3 }
R.pipe({ a: 1, b: 2, c: 3, d: 4 }, R.omit(['a', 'd'])) // => { b: 2, c: 3 }
[omitBy删除指定键]
返回原对象删除指定键(匹配断言)后的新对象
用法:
R.omitBy(object, fn)R.omitBy(fn)(object)
例子:
R.omitBy({ a: 1, b: 2, A: 3, B: 4 }, (val, key) => key.toUpperCase() === key) // => {a: 1, b: 2}
R.omitBy((val, key) => key.toUpperCase() === key)({ a: 1, b: 2, A: 3, B: 4 }) // => {a: 1, b: 2}
[set设置对象属性值]
设置对象属性的值
用法:
R.set(obj, prop, value)R.set(prop, value)(obj)
例子:
R.set({ a: 1 }, 'a', 2) // => { a: 2 }
R.pipe({ a: 1 }, R.set('a', 2)) // => { a: 2 }
[setPath设置对象属性值]
设置对象属性的值
用法:
R.setPath(obj, path, value);R.setPath(path, value)(obj);
例子:
R.setPath({ a: { b: 1 } }, ["a", "b"], 2); // => { a: { b: 2 } }
R.pipe({ a: { b: 1 } }, R.setPath(["a", "b"], 2)); // { a: { b: 2 } }
注: 上面的方法是不会对原对象修改,而是返回一个新的对象,可以自己封装一个修改原对象的方法
/**
* @description: 设置对象深度路径的值,直接在原对象上修改
*/
export function ObjSetPathCur<T>(obj: T, path: any[], value: any): void {
let currentObj: any = obj;
for(let i=0; i<path.length; i++) {
if(i < path.length-1) {
if(!currentObj[path[i]]) currentObj[path[i]] = {};
currentObj = currentObj[path[i]]
}else {
currentObj[path[i]] = value;
}
}
}
[prop获取对象属性值]
获取属性对应的值
用法:
R.prop(prop)(object)
例子:
R.pipe({ foo: 'bar' }, R.prop('foo')) // => 'bar'
[pathOr根据路径获取值]
根据路径获取值,如果值返回(undefined\null), 则返回默认值
用法:
R.pathOr(object, array, defaultValue)R.pathOr(array, defaultValue)(object)
例子:
R.pathOr({ x: 10 }, ['y'], 2) // 2
R.pathOr({ y: 10 }, ['y'], 2) // 10
R.pathOr({ x: 10, y: {name: 'ww'} }, ['y', 'name'], 'ss') // ww
R.pipe({ x: 10 }, R.pathOr(['y'], 2)) // 2
[pick摘取对象的部分属性生成新对象]
摘取对象的部分属性生成新对象
用法:
R.pick(object, [prop1, prop2])R.pick([prop1, prop2])(object)
例子:
R.pick({ a: 1, b: 2, c: 3, d: 4 }, ['a', 'd']) // => { a: 1, d: 4 }
R.pipe({ a: 1, b: 2, c: 3, d: 4 }, R.pick(['a', 'd'])) // => { a: 1, d: 4 }
[pickBy摘取对象的部分属性生成新对象]
摘取对象的部分属性(根据断言摘取)生成新对象
用法:
R.pickBy(object, fn)R.pickBy(fn)(object)
例子:
R.pickBy({ a: 1, b: 2, A: 3, B: 4 }, (val, key) => key.toUpperCase() === key) // => {A: 3, B: 4}
R.pickBy((val, key) => key.toUpperCase() === key)({ a: 1, b: 2, A: 3, B: 4 }) // => {A: 3, B: 4}
[clone深复制]
深复制值,支持类型:
Array, Object, Number, String, Boolean, Date, RegExp
用法:
R.clone(value)
参数:
value(Object): 要深复制的目标对象
返回:
(
Object): 返回新的目标对象
例子:
R.clone({ foo: 'bar' }) // {foo: 'bar'}
[keys获取对象属性集合][p][strict]
返回包含对象或数组所有key的集合
用法:
R.keys(source) \ R.keys.strict(source)
例子:
R.keys(['x', 'y', 'z']) // => ['1', '2', '3'], typed Array<string>
R.keys({ a: 'x', b: 'y', c: 'z' }) // => ['a', 'b', 'c'], typed Array<string>
R.pipe({ a: 'x', b: 'y', c: 'z' }, R.keys, R.first) // => 'a',
R.keys.strict({ a: 'x', b: 'y', c: 'z' } as const) // => ['a', 'b', 'c'], typed Array<'a' | 'b' | 'c'>
[values获取对象属性值集合][p]
返回包含对象或数组所有value的集合
用法:
R.values(source)
例子:
R.values(['x', 'y', 'z']) // => ['x', 'y', 'z']
R.values({ a: 'x', b: 'y', c: 'z' }) // => ['x', 'y', 'z']
R.pipe({ a: 'x', b: 'y', c: 'z' }, R.values, R.first) // => 'x'
[entries获取对象key/value集合][strict]
返回包含对象或数组所有key/value的集合
用法:
R.entries(object); / R.entries.strict(object);R.entries()(object); / R.entries.strict()(object);
例子:
R.entries({ a: 1, b: 2, c: 3 }); // => [['a', 1], ['b', 2], ['c', 3]]
R.entries.strict({ a: 1 } as const); // => [['a', 1]] typed Array<['a', 1]>
R.pipe({ a: 1, b: 2, c: 3 }, entries()); // => [['a', 1], ['b', 2], ['c', 3]]
R.pipe({ a: 1 } as const, entries.strict()); // => [['a', 1]] typed Array<['a', 1]>
[forEachObj遍历对象]
使用定义的回调函数遍历对象,最后返回原对象
用法:
R.forEachObj(object, fn)forEachObj(fn)(object)
例子:
R.forEachObj({ a: 1 }, (val) => {
console.log(`${val}`)
}) // "1"
R.forEachObj.indexed({ a: 1 }, (val, key, obj) => {
console.log(`${key}: ${val}`)
}) // "a: 1"
R.pipe(
{ a: 1 },
R.forEachObj((val) => console.log(`${val}`))
) // "1"
[merge对象合并]
- 两个对象合并,类似Object.assign
- b对象会覆盖a对象中所有的相同属性
用法:
R.merge(a, b)R.merge(b)(a)
例子:
R.merge({ x: 1, y: 2 }, { y: 10, z: 2 }) // => { x: 1, y: 10, z: 2 }
R.merge({ y: 10, z: 2 })({ x: 1, y: 2 }) // => { x: 1, y: 10, z: 2 }
R.mergeDeep({
id: 1,
name: 'zz',
obj: {
key1: 1
}
}, {
name: 'ss',
obj: {
key2: 2
}
})
// 结果如下
{
"id": 1,
"name": "ss",
"obj": { // 只合并到第一层
"key2": 2
}
}
[mergeDeep对象深度合并]
- 两个对象合并,如果某个Key的值是对象。则继续对该子对象进行内部遍历合并
用法:
R.mergeDeep(destination, source);R.mergeDeep(source)(destination);
例子:
R.mergeDeep({ foo: "bar", x: 1 }, { foo: "baz", y: 2 }); // => { foo: 'baz', x: 1, y: 2 }
R.pipe({ foo: "bar", x: 1 }, R.mergeDeep({ foo: "baz", y: 2 })); // => { foo: 'baz', x: 1, y: 2 }
R.mergeDeep({
id: 1,
name: 'zz',
obj: {
key1: 1
}
}, {
name: 'ss',
obj: {
key2: 2
}
})
// 结果如下
{
"id": 1,
"name": "ss",
"obj": { // 深合并
"key1": 1,
"key2": 2
}
}
[mergeAll多对象合并]
把一个对象数组合并为一个单对象
用法:
R.mergeAll(objects)
例子:
R.mergeAll([{ a: 1, b: 1 }, { b: 2, c: 3 }, { d: 10 }]) // => { a: 1, b: 2, c: 3, d: 10 }
[hasSubObject对象B是否是对象A的子对象]
如果对象B的每一个属性和对应的值 在 对象A中的存在(key和value都相等),则认为B是A的子对象(主要A允许拥有B所没有的key) 内部使用isDeepEqual方法
用法:
R.hasSubObject(data, subObject);R.hasSubObject(subObject)(data);
例子:
R.hasSubObject({ a: 1, b: 2, c: 3 }, { a: 1, c: 3 }); //=> true
R.hasSubObject({ a: 1, b: 2, c: 3 }, { b: 4 }); //=> false
R.hasSubObject({ a: 1, b: 2, c: 3 }, {}); //=> true
R.hasSubObject({ a: 1, c: 3 })({ a: 1, b: 2, c: 3 }); //=> true
R.hasSubObject({ b: 4 })({ a: 1, b: 2, c: 3 }); //=> false
R.hasSubObject({})({ a: 1, b: 2, c: 3 });
----------分割线------------
[mapKeys映射生成新的key]
映射生成新的key, 但原value保持不变
用法:
R.mapKeys(object, fn)R.mapKeys(fn)(object)
例子:
R.mapKeys({ a: 1, b: 2 }, (key, value) => key + value) // => { a1: 1, b2: 2 }
R.pipe(
{ a: 1, b: 2 },
R.mapKeys((key, value) => key + value)
) // => { a1: 1, b2: 2 }
[mapValues映射生成新的value]
映射生成新的value, 但原key保持不变
用法:
R.mapValues(object, fn)R.mapValues(fn)(object)
例子:
R.mapValues({ a: 1, b: 2 }, (value, key) => value + key) // => {a: '1a', b: '2b'}
R.pipe(
{ a: 1, b: 2 },
R.mapValues((value, key) => value + key)
) // => {a: '1a', b: '2b'}
[objOf创建只包含一对key: value的对象]
创建只包含一对key: value的对象
用法:
R.objOf(value, key)
例子:
R.objOf(10, 'a') // => { a: 10 }
R.pipe(10, R.objOf('a')) // => { a: 10 }
[evolve给对象的每一个key定义一个处理函数]
通过将evolver对象参数中包含的函数根据其对应的路径应用于data对象参数来创建新对象。 如果data对象中不存在evolver对象对应的键,则不会调用evolver中包含的函数。此外,如果evolver对象中不存在data对象的对应键,则data对象中包含的值将保持原样。
- 和toPairs相反
用法:
R.evolve(data, evolver);R.evolve(evolver)(data);
例子:
const evolver = {
count: add(1),
time: { elapsed: add(1), remaining: add(-1) },
};
const data = {
id: 10,
count: 10,
time: { elapsed: 100, remaining: 1400 },
};
evolve(data, evolver);
// => {
// id: 10,
// count: 11,
// time: { elapsed: 101, remaining: 1399 },
// }
const evolver = {
count: add(1),
time: { elapsed: add(1), remaining: add(-1) },
};
const data = {
id: 10,
count: 10,
time: { elapsed: 100, remaining: 1400 },
};
R.pipe(object, R.evolve(evolver));
// => {
// id: 10,
// count: 11,
// time: { elapsed: 101, remaining: 1399 },
// }
六.Array
数组函数分类
- 元素遍历:
forEach \ map \ mapToObj \ indexBy \ flat \ flatMap \ mapWithFeedback - 元素统计:
sumBy \ reduce \ meanBy - 元素筛选:
first \ firstBy \ nthBy \ last \ take \ takeFirstBy \ takeWhile \ takeLastWhile \ find \ findIndex \ findLast \ findLastIndex \ filter \ intersection \ sample \ shuffle - 元素剔除:
difference \ differenceWith \ drop \ dropFirstBy \ dropWhile \ dropLast \ dropLastWhile \ unique \ uniqueBy \ uniqWith - 数组拼接:
concat \ zip \ zipWith - 数组拆分:
chunk \ groupBy \ partition \ splitAt \ splitWhen - 其他:
reverse \ sort \ sortBy \ flat \ flattenDeep \ range \ join \ swapIndices \ intersectionWith \ isIncludedIn
[forEach遍历数组][i][p]
用定义的回调函数遍历数组,最后返回原数组
用法:
R.forEach(array, fn) / R.forEach.indexed(array, fn)R.forEach(fn)(array)
例子:
R.forEach([1, 2, 3], (x) => {
console.log(x)
}) // => [1, 2, 3]
R.forEach.indexed([1, 2, 3], (x, i) => {
console.log(x, i)
}) // => [1, 2, 3]
R.pipe(
[1, 2, 3],
R.forEach((x) => {
console.log(x)
})
) // => [1, 2, 3]
[map映射生成新数组][i][p]
根据定义的回调函数映射生成新数组
用法:
R.map(array, fn) / R.map.indexed(array, fn)R.map(fn)(array)
例子:
R.map([1, 2, 3], (x) => x * 2) // => [2, 4, 6]
R.map.indexed([0, 0, 0], (x, i) => i) // => [0, 1, 2]
R.pipe(
[0, 1, 2],
R.map((x) => x * 2)
) // => [0, 2, 4]
[mapToObj映射生成新对象]
根据定义的回调函数映射生成新对象
用法:
R.mapToObj(array, fn) \ R.mapToObj.indexed(array, fn)R.mapToObj(fn)(array)
例子:
R.mapToObj([1, 2, 3], (x) => [String(x), x * 2]) // => {1: 2, 2: 4, 3: 6}
R.mapToObj.indexed([0, 0, 0], (x, i) => [i, i]) // => {0: 0, 1: 1, 2: 2}
type DeviceType = '101' | '102' | '103';
type DeviceModelType = {id: DeviceType, name: string};
const models: Array<DeviceModelType> = [
{id: '101', name: '门站'},
{id: '102', name: '阀门'},
{id: '103', name: '用户'}
]
const obj2 = R.mapToObj(models, item => [item.id, item]) // type: Record<DeviceType, DeviceModelType>
R.pipe(
[1, 2, 3],
R.mapToObj((x) => [String(x), x * 2])
) // => {1: 2, 2: 4, 3: 6}
[indexBy数组转对象][i]
通过fn返回的值做为key, 把数组转为对象
用法:
R.indexBy(array, fn)R.indexBy(fn)(array)
例子:
R.indexBy(['one', 'two', 'three'], (x) => x.length) // => {3: 'two', 5: 'three'}
const arr = [{id: 1, name: 'a1'}, {id: 2, name: 'a2'}, {id: 3, name: 'a3'}]
const arrObj = R.indexBy(arr, item => item.id)
// {
// "1": {
// "id": 1,
// "name": "a1"
// },
// "2": {
// "id": 2,
// "name": "a2"
// },
// "3": {
// "id": 3,
// "name": "a3"
// }
// }
R.pipe(
['one', 'two', 'three'],
R.indexBy((x) => x.length)
) // => {3: 'two', 5: 'three'}
补充:
- 该函数返回对象的key固定是string; 有时希望Key的类型更具体。则用 mapToObj
[mapWithFeedback映射新数组-递归统计][i]
映射函数的第一个参数是上一次计算的结果或初始值。第二个参数是当前数组项。函数返回的结果作为下一次调用的第一个参数。
用法:
R.mapWithFeedback(items, fn, initialValue) / R.mapWithFeedback.indexed(items, fn, initialValue)R.mapWithFeedback(fn, initialValue)(array)
例子:
R.mapWithFeedback([1, 2, 3, 4, 5], (prev, x) => prev + x, 100); // => [101, 103, 106, 110, 115]
R.mapWithFeedback.indexed(
[1, 2, 3, 4, 5],
(prev, x, i, array) => prev + x,
100,
); // => [101, 103, 106, 110, 115]
R.pipe(
[1, 2, 3, 4, 5],
R.mapWithFeedback((prev, x) => prev + x, 100),
); // => [101, 103, 106, 110, 115]
R.pipe(
[1, 2, 3, 4, 5],
R.mapWithFeedback.indexed((prev, x, i, array) => prev + x, 100),
); // => [101, 103, 106, 110, 115]
[sumBy数组求和][i]
把回调函数返回的值全部加起来返回
用法:
R.sumBy(array, fn) / R.sumBy.indexed(array, fn)R.sumBy(fn)(array)
例子:
R.sumBy([{ a: 5 }, { a: 1 }, { a: 3 }], (x) => x.a) // 9
R.pipe(
[{ a: 5 }, { a: 1 }, { a: 3 }],
R.sumBy((x) => x.a)
) // 9
[reduce数组累积计算][i]
类似js元素reduce, 数组的每个元素都会调用一次指定的回调函数fn. 上一个fn返回的结果,作为下一个fn的一个参数使用。
用法:
R.reduce(items, fn, initialValue)R.reduce.indexed(items, fn, initialValue)
参数:
items(any): 数组元素fn(Function): 指定的回调函数 函数接收四个参数acc//上一个回调函数的返回值, x//当前数组元素, i//当前元素索引, array//原数组initialValue(any): 初始值,作为第一个回调函数的acc值
例子:
R.reduce([1, 2, 3, 4, 5], (acc, x) => acc + x, 100) // => 115
R.reduce.indexed([1, 2, 3, 4, 5], (acc, x, i, array) => acc + x, 100) // => 115
[meanBy数组平均值][i]
返回数组使用断言函数后的平均值
用法:
R.meanBy(array, fn) \ R.meanBy.indexed(array, fn);R.meanBy(fn)(array) \ R.meanBy.indexed(fn)(array)
例子:
R.meanBy([{ a: 5 }, { a: 1 }, { a: 3 }], (x) => x.a); // 3
R.pipe(
[{ a: 5 }, { a: 1 }, { a: 3 }],
R.meanBy((x) => x.a),
); // 3
[first获取第一个元素][p]
获取数组第一个元素
用法:
R.first(array)R.first()(array);
例子:
R.first([1, 2, 3]) // => 1
R.first([]) // => undefined
R.pipe(
[1, 2, 4, 8, 16],
R.filter((x) => x > 3),
R.first(),
(x) => x + 1
) // => 5
[firstBy自定义排序获取第一个元素][p]
获取数组中第一个符合所提供顺序规则的元素
用法:
R.firstBy(data, ...rules);R.firstBy(...rules)(data);
例子:
const max = R.firstBy([1, 2, 3], [R.identity, "desc"]); // => 3;
const min = R.firstBy([1, 2, 3], R.identity); // => 1;
const data = [{ a: "a" }, { a: "aa" }, { a: "aaa" }] as const;
const maxBy = R.firstBy(data, [(item) => item.a.length, "desc"]); // => { a: "aaa" };
const minBy = R.firstBy(data, (item) => item.a.length); // => { a: "a" };
const data = [
{ type: "cat", size: 1 },
{ type: "cat", size: 2 },
{ type: "dog", size: 3 },
] as const;
const multi = R.firstBy(data, R.prop("type"), [R.prop("size"), "desc"]); // => {type: "cat", size: 2}
--------
const maxBy = R.pipe(data, R.firstBy([(item) => item.a.length, "desc"])); // => { a: "aaa" };
const minBy = R.pipe(
data,
R.firstBy((item) => item.a.length),
); // => { a: "a" };
const data = [
{ type: "cat", size: 1 },
{ type: "cat", size: 2 },
{ type: "dog", size: 3 },
] as const;
const multi = R.pipe(data, R.firstBy(R.prop("type"), [R.prop("size"), "desc"])); // => {type: "cat", size: 2}
[nthBy自定义排序获取第n个元素]
获取数组中第n个符合所提供顺序规则的元素
用法:
R.nthBy(data, index, ...rules);R.nthBy(index, ...rules)(data);
例子:
R.nthBy([2, 1, 4, 5, 3], 2, identity); // => 3
R.pipe([2, 1, 4, 5, 3], R.nthBy(2, identity)); // => 3
[last获取最后一个元素][p]
获取数组最后一个元素
注意: 在pipe函数中,使用last() 代替last; 因为last会丢失类型推断
用法:
R.last(array)
例子:
R.last([1, 2, 3]) // => 3
R.last([]) // => undefined
R.pipe(
[1, 2, 4, 8, 16],
R.filter((x) => x > 3),
R.last(),
(x) => x + 1
) // => 17
[take获取前n个元素][p]
从数组中返回前n个元素组成的新数组(数组内的元素如果是对象的话,只是浅引用,而不会深复制)
用法:
R.take(array, n)R.take(n)(array)
例子:
R.take([1, 2, 3, 4, 3, 2, 1], 3) // => [1, 2, 3]
R.pipe([1, 2, 3, 4, 3, 2, 1], R.take(3)) // => [1, 2, 3]
[takeFirstBy获取前n个元素][p]
根据提供的排序条件从数组中返回前n个元素组成的新数组(数组内的元素如果是对象的话,只是浅引用,而不会深复制)
用法:
R.takeFirstBy(data, n, ...rules)R.takeFirstBy(n, ...rules)(data)
例子:
R.takeFirstBy(["aa", "aaaa", "a", "aaa"], 2, (x) => x.length); // => ['a', 'aa']
R.pipe(
["aa", "aaaa", "a", "aaa"],
R.takeFirstBy(2, (x) => x.length),
); // => ['a', 'aa']
[takeWhile获取前n个元素]
从数组中返回前n(n为断言第一次返回false处的索引)个元素组成的新数组(数组内的元素如果是对象的话,只是浅引用,而不会深复制)
用法:
R.takeWhile(array, fn)R.takeWhile(fn)(array)
例子:
R.takeWhile([1, 2, 3, 4, 3, 2, 1], (x) => x !== 4) // => [1, 2, 3]
R.pipe(
[1, 2, 3, 4, 3, 2, 1],
R.takeWhile((x) => x !== 4)
) // => [1, 2, 3]
[takeLastWhile 获取后n个元素]
语法同上
[find筛选一个元素][i][p]
返回数组中第一个符合断言的元素,如果都没有,返回undefined
用法:
R.find(items, fn) \ R.find.indexed(items, fn)R.find(fn)(items)
例子:
R.find([1, 3, 4, 6], (n) => n % 2 === 0) // => 4
R.find.indexed([1, 3, 4, 6], (n, i) => i>10) // undefined
R.pipe(
[1, 3, 4, 6],
R.find((n) => n % 2 === 0)
) // => 4
[findIndex筛选一个元素][i][p]
返回数组中第一个符合断言的元素的索引,如果都没有,返回-1
用法:
R.findIndex(items, fn) \ R.findIndex.indexed(items, fn)R.findIndex(fn)(items)
例子:
R.findIndex([1, 3, 4, 6], (n) => n % 2 === 0) // => 2
R.findIndex.indexed([1, 3, 4, 6], (n, i) => i>10) // -1
R.pipe(
[1, 3, 4, 6],
R.findIndex((n) => n % 2 === 0)
) // => 2
[findLast从后开始筛选一个元素][i][p]
从数组的后面开始,返回第一个符合断言的元素,如果都没有,返回undefined
用法:
R.findLast(items, fn) \ R.findLast.indexed(items, fn)R.findLast(fn)(items) \ R.findLast.indexed(fn)(items)
例子:
R.findLast([1, 3, 4, 6], (n) => n % 2 === 1); // => 3
R.findLast.indexed([1, 3, 4, 6], (n, i) => n % 2 === 1); // => 3
---------
R.pipe(
[1, 3, 4, 6],
R.findLast((n) => n % 2 === 1),
); // => 3
R.pipe(
[1, 3, 4, 6],
R.findLast.indexed((n, i) => n % 2 === 1),
); // => 3
[findLastIndex从后开始筛选一个元素][i][p]
从数组的后面开始,返回第一个符合断言的元素的索引,如果都没有,返回-1
用法:
R.findLastIndex(items, fn) \ R.findLastIndex.indexed(items, fn)R.findLastIndex(fn)(items) \ R.findLastIndex.indexed(fn)(items)
例子:
R.findLastIndex([1, 3, 4, 6], (n) => n % 2 === 1); // => 1
R.findLastIndex.indexed([1, 3, 4, 6], (n, i) => n % 2 === 1); // => 1
R.pipe(
[1, 3, 4, 6],
R.findLastIndex((n) => n % 2 === 1),
); // => 1
R.pipe(
[1, 3, 4, 6],
R.findLastIndex.indexed((n, i) => n % 2 === 1),
); // => 1
[filter筛选多个元素][i][p]
在数组中筛选符合回调函数中的条件的元素
用法:
R.filter(array, fn) \ R.filter.indexed(array, fn)R.filter(fn)(array)
例子:
R.filter([1, 2, 3], (x) => x % 2 === 1) // => [1, 3]
R.filter.indexed([1, 2, 3], (x, i, array) => x % 2 === 1) // => [1, 3]
R.pipe(
[1, 2, 3],
R.filter((x) => x % 2 === 1)
) // => [1, 3]
[intersection数组交集][p]
返回两个数组的交集
用法:
R.intersection(array, other)R.intersection(other)(array)
例子:
R.intersection([1, 2, 3], [2, 3, 5]) // => [2, 3]
R.intersection([2, 3, 5])([1, 2, 3]) // => [2, 3]
[sample数组随机取样][p]
根据取样数从数组中随机挑选一份子集
用法:
R.sample(array, sampleSize)R.sample(sampleSize)(array);
例子:
R.sample(["hello", "world"], 1); // => ["hello"] // typed string[]
R.sample(["hello", "world"] as const, 1); // => ["world"] // typed ["hello" | "world"]
R.sample(1)(["hello", "world"]); // => ["hello"] // typed string[]
R.sample(1)(["hello", "world"] as const); // => ["world"] // typed ["hello" | "world"]
[shuffle数组洗牌][p]
数组重新随机打乱顺序后返回
用法:
R.shuffle(array);R.shuffle()(array);
例子:
R.shuffle([4, 2, 7, 5]); // => [7, 5, 4, 2]
R.pipe([4, 2, 7, 5], R.shuffle()); // => [7, 5, 4, 2]
[difference根据另一个数组来排除值][p]
根据另一个数组来排除值
用法:
R.difference(array, other)R.difference(other)(array)
例子:
R.difference([1, 2, 3, 4], [2, 5, 3]) // => [1, 4]
R.difference([2, 5, 3])([1, 2, 3, 4]) // => [1, 4]
R.pipe(
[1, 2, 3, 4, 5, 6], // only 4 iterations
R.difference([2, 3]),
R.take(2)
) // => [1, 4]
[differenceWith根据另一个数组来排除值][p]
- 根据另一个数组来排除值
- 元素的比较由自定义的比较器来进行
用法:
R.differenceWith(array, other, isEquals)R.differenceWith(other, isEquals)(array)
参数:
- isEquals: (a, b) => Boolean; isEqual是一个比较方法,a和b分别是两个数组内的元素,结果返回这两个元素是否相等
例子:
R.differenceWith(
[{ a: 1 }, { a: 2 }, { a: 3 }, { a: 4 }],
[{ a: 2 }, { a: 5 }, { a: 3 }],
(arr1, arr2) => arr1.a == arr2.a
) // => [{a: 1}, {a: 4}]
R.differenceWith(
[{ a: 2 }, { a: 5 }, { a: 3 }],
R.isDeepEqual
)([{ a: 1 }, { a: 2 }, { a: 3 }, { a: 4 }]) // => [{a: 1}, {a: 4}]
R.pipe(
[{ a: 1 }, { a: 2 }, { a: 3 }, { a: 4 }, { a: 5 }, { a: 6 }], // only 4 iterations
R.differenceWith([{ a: 2 }, { a: 3 }], R.isDeepEqual),
R.take(2)
) // => [{a: 1}, {a: 4}]
[drop移除前n个元素][p]
移除数组的前n个元素
用法:
R.drop(array, n)R.drop(n)(array)
例子:
R.drop([1, 2, 3, 4, 5], 2) // => [3, 4, 5]
R.drop(2)([1, 2, 3, 4, 5]) // => [3, 4, 5]
[dropFirstBy对数组排序后移除前n个元素]
根据提供的排序条件从数据中删除前n个项目。这样可以避免在删除项目之前对数组进行排序。这个函数的复杂度是O(Nlogn). 其中N是数组长度
用法:
R.dropFirstBy(array, n, ...rules);R.dropFirstBy(n, ...rules)(array
例子:
R.dropFirstBy(["aa", "aaaa", "a", "aaa"], 2, (x) => x.length); // => ['aaa', 'aaaa']
R.pipe(
["aa", "aaaa", "a", "aaa"],
R.dropFirstBy(2, (x) => x.length),
); // => ['aaa', 'aaaa']
[dropWhile根据断言移除前n个元素]
从前往后移除数组元素,直到断言返回false. 返回剩下的元素数组(包含false的元素)
用法:
R.dropWhile(array, predicate);R.dropWhile(predicate)(array)
例子:
R.dropWhile([1, 2, 10, 3, 4], (x) => x < 10); // => [10, 3, 4]
R.pipe(
[1, 2, 10, 3, 4],
R.dropWhile((x) => x < 10),
); // => [10, 3, 4]
[dropLast移除后n个元素]
移除数组的后n个元素
用法:
R.dropLast(array, n)R.dropLast(n)(array)
例子:
R.dropLast([1, 2, 3, 4, 5], 2) // => [1, 2, 3]
R.dropLast(2)([1, 2, 3, 4, 5]) // => [1, 2, 3]
[dropLastWhile根据断言移除后n个元素]
从后往前移除数组元素,直到断言返回false. 返回剩下的元素数组(包含false的元素)
用法:
R.dropLastWhile(array, predicate);R.dropLastWhile(predicate)(array)
例子:
R.dropLastWhile([1, 2, 10, 3, 4], (x) => x < 10); // => [1, 2, 10]
R.pipe(
[1, 2, 10, 3, 4],
R.dropLastWhile((x) => x < 10),
); // => [1, 2, 10]
[unique数组去重][p]
- 返回一个新数组,其中只包含原始列表中每个元素的一个副本。
- 对象元素通过引用地址进行比较。
用法:
R.unique(array)
例子:
R.unique([1, 2, 2, 5, 1, 6, 7]) // => [1, 2, 5, 6, 7]
const zs = {name: '张三'}
R.unique([zs, zs, {name: '李四'}, {name: '张三', age: 14}]) // 引用地址进行比较
// '[{"name":"张三"},{"name":"李四"},{"name":"张三","age":14}]'
R.unique([{name: '张三'}, {name: '张三'}, {name: '李四'}, {name: '张三', age: 14}]) // 引用地址进行比较
// '[{"name":"张三"},{"name":"张三"},{"name":"李四"},{"name":"张三","age":14}]'
R.pipe(
[1, 2, 2, 5, 1, 6, 7], // only 4 iterations
R.unique(),
R.take(3)
) // => [1, 2, 5]
[uniqueBy 数组去重][p]
- 返回一个新数组,该数组只包含由函数转换后的值的唯一副本。
- 对象元素通过引用地址进行比较。(参数unique)
用法:
R.uniqueBy(array, fn)
例子:
R.uniqueBy(
[{ n: 1 }, { n: 2 }, { n: 2 }, { n: 5 }, { n: 1 }, { n: 6 }, { n: 7 }],
(obj) => obj.n
) // => [{n: 1}, {n: 2}, {n: 5}, {n: 6}, {n: 7}]
R.pipe(
[{ n: 1 }, { n: 2 }, { n: 2 }, { n: 5 }, { n: 1 }, { n: 6 }, { n: 7 }], // only 4 iterations
R.uniqueBy((obj) => obj.n),
R.take(3)
) // => [{n: 1}, {n: 2}, {n: 5}]
[uniqWith 数组去重]
- 返回一个去重的新数组,是否重复由用户自定义的比较器决定。
用法:
R.uniqWith(array, isEquals)R.uniqWith(isEquals)(array)
例子:
R.uniqWith(
[{ a: 1 }, { a: 2 }, { a: 2 }, { a: 5 }, { a: 1 }, { a: 6 }, { a: 7 }],
R.isDeepEqual
) // => [{a: 1}, {a: 2}, {a: 5}, {a: 6}, {a: 7}]
R.uniqWith(R.isDeepEqual)([
{ a: 1 },
{ a: 2 },
{ a: 2 },
{ a: 5 },
{ a: 1 },
{ a: 6 },
{ a: 7 },
]) // => [{a: 1}, {a: 2}, {a: 5}, {a: 6}, {a: 7}]
R.pipe(
[{ a: 1 }, { a: 2 }, { a: 2 }, { a: 5 }, { a: 1 }, { a: 6 }, { a: 7 }], // only 4 iterations
R.uniqWith(R.isDeepEqual),
R.take(3)
) // => [{a: 1}, {a: 2}, {a: 5}]
[concat数组拼接]
联合两个数组
用法:
R.concat(arr1, arr2)R.concat(arr2)(arr1)
例子:
R.concat([1, 2, 3], ['a']) // [1, 2, 3, 'a']
R.concat(['a'])([1, 2, 3]) // [1, 2, 3, 'a']
[zip两个数组内部元素组合]
把两个数组组合成二维数组,把相同索引处的值组合在一起。返回的数组长度以提供的两个数组中最短的那个为主
用法:
R.zip(first, second)R.zip(second)(first)
例子:
R.zip([1, 2, 3], ['a', 'b']) // => [[1, 'a'], [2, 'b']]
R.zip(['a', 'b'])([1, 2]) // => [[1, 'a'], [2, 'b']]
[zipWith两个数组内部元素组合]
通过自定义函数把两个数组组合到一起
用法:
R.zipWith(first, second, fn)
例子:
R.zipWith(['1', '2', '3'], ['a', 'b', 'c'], (a, b) => a + b) // => ['1a', '2b', '3c']
R.zipWith((a, b) => a + b)(['1', '2', '3'], ['a', 'b', 'c']) // => ['1a', '2b', '3c']
[chunk按固定长度分多块]
把数组按固定长度分割,如果最后一块数组的长度不够,则只保留剩下的值
用法:
R.chunk(array, size)R.chunk(size)(array)
参数:
array(Array): 要分割的数据size(Number): 要分割的长度
返回:
(
Array): 返回新的二维数组
例子:
R.chunk(['a', 'b', 'c', 'd'], 2) // => [['a', 'b'], ['c', 'd']]
R.chunk(['a', 'b', 'c', 'd'], 3) // => [['a', 'b', 'c'], ['d']]
R.chunk(2)(['a', 'b', 'c', 'd']) // => [['a', 'b'], ['c', 'd']]
R.chunk(3)(['a', 'b', 'c', 'd']) // => [['a', 'b', 'c'], ['d']]
[groupBy分组拆分为对象][i]
将集合分组拆分为对象,并根据通过fn运行每个值的结果进行分组。
用法:
R.groupBy(array, fn)R.groupBy(fn)(array)
例子:
R.groupBy(['one', 'two', 'three'], (x) => x.length) // => {3: ['one', 'two'], 5: ['three']}
R.pipe(
['one', 'two', 'three'],
R.groupBy((x) => x.length)
) // => {3: ['one', 'two'], 5: ['three']}
[partition根据断言分割为两部分][i]
分割数组为两部分,第一部分是匹配断言的集合。第二部分是未匹配断言的集合
用法:
R.partition(array, fn)R.partition(fn)(array)
例子:
R.partition(['one', 'two', 'forty two'], (x) => x.length === 3) // => [['one', 'two'], ['forty two']]
R.pipe(
['one', 'two', 'forty two'],
R.partition((x) => x.length === 3)
) // => [['one', 'two'], ['forty two']]
[splitAt根据索引分割为两部分]
根据索引分割数组为两部分
用法:
R.splitAt(array, index)R.splitAt(index)(array)
例子:
R.splitAt([1, 2, 3], 1) // => [[1], [2, 3]]
R.splitAt([1, 2, 3, 4, 5], -1) // => [[1, 2, 3, 4], [5]]
[splitWhen根据索引分割为两部分]
根据断言第一次返回true的元素的索引分割数组为两部分
用法:
R.splitWhen(array, fn)R.splitWhen(fn)(array)
例子:
R.splitWhen([1, 2, 3], (x) => x === 2) // => [[1], [2, 3]]
R.splitWhen((x) => x === 2)([1, 2, 3]) // => [[1], [2, 3]]
[reverse倒置数组]
倒置数组
用法:
R.reverse(arr)R.reverse()(array)
例子:
R.reverse([1, 2, 3]) // [3, 2, 1]
R.reverse()([1, 2, 3]) // [3, 2, 1]
[sort数组排序]
数组排序, 这个比较函数一次接收两个值,并且返回一个number, 如果正向排序就返回负数,如果反向排序就返回正数,如果相等不用换位置就返回0
用法:
R.sort(items, (a, b) => Number)R.sort(cmp)(items)
例子:
R.sort([4, 2, 7, 5], (a, b) => a - b) // => [2, 4, 5, 7]
R.pipe(
[4, 2, 7, 5],
R.sort((a, b) => a - b)
) // => [2, 4, 5, 7]
[sortBy数组排序]
- 显式声明排序方式asc / desc (不指定就默认asc)
- 可以多个排序函数一起作用,最前面的优先级最高
用法:
R.sortBy(array, ...sorts)R.sortBy(...sorts)(array)
参数:
参数名(参数类型): 参数描述
返回:
(
返回类型): 返回描述
例子:
R.sortBy([{ a: 1 }, { a: 3 }, { a: 7 }, { a: 2 }], (x) => x.a)
// => [{ a: 1 }, { a: 2 }, { a: 3 }, { a: 7 }]
R.sortBy(
[
{ color: 'red', weight: 2 },
{ color: 'blue', weight: 3 },
{ color: 'green', weight: 1 },
{ color: 'purple', weight: 1 },
],
[(x) => x.weight, 'asc'],
(x) => x.color
)
// =>
// {color: 'purple', weight: 1},
// {color: 'green', weight: 1},
// {color: 'red', weight: 2},
// {color: 'blue', weight: 3},
[flat扁平化数组][p]
扁平化第一层数组
用法:
R.flat(data); \ R.flat(data, depth);R.flat()(data); \ R.flat(depth)(data);
例子:
R.flat([[1, 2], [3, 4], [5], [[6]]]); // => [1, 2, 3, 4, 5, [6]]
R.flat([[[1]], [[2]]], 2); // => [1, 2]
R.pipe([[1, 2], [3, 4], [5], [[6]]], R.flat()); // => [1, 2, 3, 4, 5, [6]]
R.pipe([[[1]], [[2]]], R.flat(2)); // => [1, 2]
[flatMap映射数组并扁平化结果][p]
使用定义的回调函数映射数组中的每个元素,并展平映射的结果。
用法:
R.flatMap(array, fn);R.flatMap(fn)(array);
例子:
R.flatMap([1, 2, 3], (x) => [x, x * 10]); // => [1, 10, 2, 20, 3, 30]
R.pipe(
[1, 2, 3],
R.flatMap((x) => [x, x * 10]),
); // => [1, 10, 2, 20, 3, 30]
[range生成固定范围的number数组]
返回一个Number数组,范围时从start(包含)到end(不包含)
用法:
range(start, end)
例子:
R.range(1, 5) // => [1, 2, 3, 4]
[length统计集合长度]
返回集合长度
用法:
R.length(array);R.length()(array);
例子:
R.length([1, 2, 3]); // => 3
R.pipe([1, 2, 3], R.length()); // => 3
[join数组拼接为字符串]
把数组拼接为一个字符串。如果数组是元祖。这字符串结果是stricter(更严格)的
用法:
R.join(data, glue);R.join(glue)(data);
例子:
R.join([1, 2, 3], ","); // => "1,2,3" (typed `string`)
R.join(["a", "b", "c"], ""); // => "abc" (typed `string`)
R.join(["hello", "world"] as const, " "); // => "hello world" (typed `hello world`)
R.pipe([1, 2, 3], R.join(",")); // => "1,2,3" (typed `string`)
R.pipe(["a", "b", "c"], R.join("")); // => "abc" (typed `string`)
R.pipe(["hello", "world"] as const, R.join(" ")); // => "hello world" (typed `hello world`)
[swapIndices交换元素位置]
在提供的两个索引处交换数组或字符串中两个元素的位置
用法:
swapIndices(data, index1, index2);swapIndices(index1, index2)(data);
例子:
swapIndices(["a", "b", "c"], 0, 1); // => ['b', 'a', 'c']
swapIndices("abc", 0, 1); // => 'bac'
swapIndices(0, 1)(["a", "b", "c"]); // => ['b', 'a', 'c']
swapIndices(0, -1)("abc"
[intersectionWith获取数组交叉部分]
返回基于自定义比较器函数的相交值列表,自定义比较器函数用于比较两个数组元素
用法:
R.intersectionWith(array, other, comparator);R.intersectionWith(other, comparator)(array);
例子:
R.intersectionWith(
[
{ id: 1, name: "Ryan" },
{ id: 3, name: "Emma" },
],
[3, 5],
(a, b) => a.id === b,
); // => [{ id: 3, name: 'Emma' }]
R.intersectionWith(
[3, 5],
(a, b) => a.id === b,
)([
{ id: 1, name: "Ryan" },
{ id: 3, name: "Emma" },
]); // => [{ id: 3, name: 'Emma' }]
[isIncludedIn数据A是否包含在数据B中]
这是对Array.protptype.includes和Set.propotype.has的封装
用法:
R.isIncludedIn(data, container);R.isIncludedIn(container)(data);
例子:
R.isIncludedIn(2, [1, 2, 3]); // => true
R.isIncludedIn(4, [1, 2, 3]); // => false
const data = "cat" as "cat" | "dog" | "mouse";
R.isIncludedIn(data, ["cat", "dog"] as const); // true (typed "cat" | "dog");
// -----------------
R.pipe(2, R.isIncludedIn([1, 2, 3])); // => true
R.pipe(4, R.isIncludedIn([1, 2, 3])); // => false
const data = "cat" as "cat" | "dog" | "mouse";
R.pipe(data, R.isIncludedIn(["cat", "dog"] as const)); // => true (typed "cat" | "dog");
七.Function
[pipe函数组合-左到右]
组合函数,执行顺序为从左到右,左边一个函数的返回值是下一个函数的输入值(参数)
用法:
R.pipe(data, op1, op2, op3)
例子:
R.pipe(
[1, 2, 3, 4],
R.map((x) => x * 2),
(arr) => [arr[0] + arr[1], arr[2] + arr[3]]
) // => [6, 14]
[pipedpipe的数据在后版本]
piped 的数据在后版本 第一个方法必须给类型注释,后面的方法会根据前面的自动推断
用法:
R.piped(...ops)(data);
例子:
R.filter(
[{ a: 1 }, { a: 2 }, { a: 3 }],
R.piped(R.prop("a"), (x) => x % 2 === 0),
); // => [{ a: 2 }]
[allPass断言组合-都通过]
对于输入的数据,是否所有的断言都通过
用法:
R.allPass(data, fns)R.allPass(fns)(data)
参数:
data(any): 要断言的数据fns(Array<Function>): 断言方法数组
返回:
(
Boolean): 是否所有的断言都通过
例子:
const isDivisibleBy3 = (x: number) => x % 3 === 0
const isDivisibleBy4 = (x: number) => x % 4 === 0
const fns = [isDivisibleBy3, isDivisibleBy4]
R.allPass(12, fns) // => true
R.allPass(8, fns) // => false
R.allPass(fns)(12) // => true
R.allPass(fns)(8) // => false
[anyPass断言组合-任意一个通过]
对于输入的数据,是否有任意一个断言通过
用法:
R.anyPass(data, fns)R.anyPass(fns)(data)
参数:
data(any): 要断言的数据fns(Array<Function>): 断言方法数组
返回:
(
Boolean): 是否所有的断言都通过
例子:
const isDivisibleBy3 = (x: number) => x % 3 === 0
const isDivisibleBy4 = (x: number) => x % 4 === 0
const fns = [isDivisibleBy3, isDivisibleBy4]
R.anyPass(8, fns) // => true
R.anyPass(11, fns) // => false
R.anyPass(fns)(8) // => true
R.anyPass(fns)(11) // => false
[once只执行一次的函数]
创建只执行一次的函数,后面的重复调用都只会返回第一次调用的结果
用法:
R.once(fn)
例子:
const initialize = R.once(createApplication)
initialize()
initialize()
// => `createApplication` is invoked once
[times一次执行n次fn函数]
执行n次fn函数,并把每次函数返回的值并为一个数组返回.fn接收的参数是0~n-1
用法:
R.time(n, fn)R.time(fn)(n)
例子:
times(identity, 5) //=> [0, 1, 2, 3, 4]
times(5)(identity) //=> [0, 1, 2, 3, 4]
[identity返回原参数]
把传入的参数再返回出去
用法:
R.identity(data)
例子:
R.identity('foo') // => 'foo'
[tap执行某个方法后返回原参数]
1.调用具有给定值的给定函数,然后返回给定值。所提供函数的返回值将被忽略 2.这允许“窃听”管道中的函数序列,以对中间结果执行副作用。
用法:
R.tap(value, fnR.tap(fn)(value);
例子:
R.tap("foo", console.log); // => "foo"
R.pipe(
[-5, -1, 2, 3],
R.filter((n) => n > 0),
R.tap(console.log), // prints [2, 3] 这里console.log返回的是Undefined.但tap放返回的依然是他接收到的数据
R.map((n) => n * 2),
); // => [4, 6]
[purry创建data-first和data-last签名的函数]
创建data-first和data-last签名的函数, purry是一个动态函数并且没有类型安全,它应该被一个拥有合适类型的函数包装起来
用法:
R.purry(fn, arguments)
例子:
function _findIndex(array: any, fn: any) {
for (let i = 0; i < array.length; i++) {
if (fn(array[i])) {
return i;
}
}
return -1;
}
// data-first
function findIndex<T>(array: T[], fn: (item: T) => boolean): number;
// data-last
function findIndex<T>(fn: (item: T) => boolean): (array: T[]) => number;
function findIndex() {
return R.purry(_findIndex, arguments);
}
findIndex([1,2,3], item => item == 2) // 1
findIndex(item => item == 2)([1,2,3]) // 1
[conditional条件匹配(switch)]
执行第一个匹配条件的函数。类似于switch
用法:
R.conditional(data, ...cases);R.conditional(...cases)(data)
例子:
const nameOrId = 3 as string | number;
R.conditional(
nameOrId,
[R.isString, (name) => `Hello ${name}`],
[R.isNumber, (id) => `Hello ID: ${id}`],
R.conditional.defaultCase(
(something) => `Hello something (${JSON.stringify(something)})`,
),
); //=> 'Hello ID: 3'
const nameOrId = 3 as string | number;
R.pipe(
nameOrId,
R.conditional(
[R.isString, (name) => `Hello ${name}`],
[R.isNumber, (id) => `Hello ID: ${id}`],
R.conditional.defaultCase(
(something) => `Hello something (${JSON.stringify(something)})`,
),
),
); //=> 'Hello ID: 3'
[debounce 去抖动]
包装一个函数,如果这个函数在短时间内调用多次,之后执行一次;
用法:
R.debounce(func, options);
参数:
options: {timing: 'both'|'leading'| 'trailing', waitMs: number}- options.timing: 调用的位置 leading 头部调用,trailing 尾部调用,both 首尾各调用一次
- options.waitMs: 冷却时间
返回值:
{
call: (...args) => any, // 调用被包装的函数并传参
cancel: () => void, // 如果在冷却期调用,则取消冷却期结束后应该调用的函数(但不影响下一轮的冷却期)
flush: () => void, // 如果在冷却期调用,则立即触发冷却期结束事件
isPending: boolean, // 是否处于冷却期
cacheValue: any, // 上一次被包装函数调用后的返回值(每一次调用被包装函数都会把它的返回值缓存下来)
}
例子:
const debouncer = debounce(identity, { timing: "trailing", waitMs: 1000 });
const result1 = debouncer.call(1); // => undefined
const result2 = debouncer.call(2); // => undefined
// after 1 second
const result3 = debouncer.call(3); // => 2
// after 1 second
debouncer.cachedValue; // => 3
[doNothing接收任意参数但不操作]
接收任意参数但不操作,并且返回void
用法:
R.doNothing()
例子:
myApi({ onSuccess: handleSuccess, onError: R.doNothing() });
myApi({ onSuccess: isDemoMode ? R.doNothing() : handleSuccess });
八.Guard 守卫
[isDeepEqual深度比较两个值是否相等]
深度比较两个值是否相等; 单一值用 === 数组和对象都会深度遍历去比较的 时间Date等特殊值也会取它的值来比较的(而不是比较对象的内存地址应用)
用法:
R.isDeepEqual(data, other);R.isDeepEqual(other)(data);
例子:
R.isDeepEqual(1, 1); //=> true
R.isDeepEqual(1, "1"); //=> false
R.isDeepEqual([1, 2, 3], [1, 2, 3]); //=> true
R.pipe(1, R.isDeepEqual(1)); //=> true
R.pipe(1, R.isDeepEqual("1")); //=> false
R.pipe([1, 2, 3], R.isDeepEqual([1, 2, 3])); //=> true
[isArray是否是数组]
用于检查传递的参数是否为数组,并相应地缩小其类型
用法:
R.isArray(data)
例子:
R.isArray([5]) //=> true
R.isArray([]) //=> true
R.isArray('somethingElse') //=> false
[isBoolean是否是布尔值]
用于检查传递的参数是否为布尔值,并相应地缩小其类型
用法:
R.isBoolean(data)
例子:
R.isBoolean(true) //=> true
R.isBoolean(false) //=> true
R.isBoolean('somethingElse') //=> false
[isDate是否是时间]
用于检查传递的参数是否为时间,并相应地缩小其类型
用法:
R.isDate(data)
例子:
R.isDate(new Date()) //=> true
R.isDate('somethingElse') //=> false
[isDefined是否已定义]
用于检查传递的参数是否已定义,并相应地缩小其类型
用法:
R.isDefined(data)
例子:
R.isDefined('string') //=> true
R.isDefined(null) //=> false
R.isDefined(undefined) //=> false
[isError是否是Error对象]
用于检查传递的参数是否是Error,并相应地缩小其类型
用法:
R.isError(data)
例子:
R.isError(new Error('message')) //=> true
R.isError('somethingElse') //=> false
[isFunction是否是函数]
用于检查传递的参数是否是函数,并相应地缩小其类型
用法:
R.isFunction(data)
例子:
R.isFunction(() => {}) //=> true
R.isFunction('somethingElse') //=> false
[isNullish是否是空]
用于检查传递的参数是否是空(null \ undefined),并相应地缩小其类型
用法:
R.isNullish(data)
例子:
R.iisNullish(undefined) //=> true
R.iisNullish(null) //=> true
R.iisNullish('somethingElse') //=> false
[isNonNullish是否是有效值]
用于检查传递的参数是否非null和非undefined,并相应地缩小其类型
用法:
R.isNonNullish(data)
例子:
R.isNonNullish("string"); //=> true
R.isNonNullish(null); //=> false
R.isNonNullish(undefined); //=> false
[isNonNull是否非null]
用于检查传递的参数是否非null,并相应地缩小其类型 主要undefined也是非null
用法:
R.isNonNull(data)
例子:
R.isNonNull("string"); //=> true
R.isNonNull(null); //=> false
R.isNonNull(undefined); //=> true
[isNot对守卫函数取反]
把原守卫函数当断言使用,并返回一个反向的守卫函数
用法:
R.isNot(R.isTruthy)(data)
例子:
R.isNot(R.isTruthy)(false) //=> true
R.isNot(R.isTruthy)(true) //=> false
[isNumber是否是数字]
用于检查传递的参数是否是数字,并相应地缩小其类型
用法:
R.isNumber(data)
例子:
R.isNumber(1) //=> true
R.isNumber('notANumber') //=> false
R.isNumber('1') //=> false
[isObjectType是否是对象类型]
需要注意的是,在JavaScript中,许多实体都被视为对象,如Arrays, Classes, RegExps, Maps, Sets, Dates, URLs, Promise, Errors等。 虽然从技术上讲,null也是一个对象,但此函数不将null视为对象,因此更容易缩小null的范围。 对于普通对象,考虑用 isPlainObject 代替
用法:
R.isObjectType(data)
例子:
// true
R.isObjectType({}); //=> true
R.isObjectType([]); //=> true
R.isObjectType(Promise.resolve("something")); //=> true
R.isObjectType(new Date()); //=> true
R.isObjectType(new Error("error")); //=> true
// false
R.isObjectType("somethingElse"); //=> false
R.isObjectType(null); //=> false
[isPlainObject是否是普通对象]
一般指非Arrays, Classes, RegExps, Maps, Sets, Dates, URLs, Promise, Errors等 的 普通对象。
用法:
R.isPlainObject(data)
例子:
// true
R.isPlainObject({}); //=> true
R.isPlainObject({ a: 123 }); //=> true
R.isPlainObject({ a: 123, abj: { key1: new Date() } }); //=> true
// false
R.isPlainObject([]); //=> false
R.isPlainObject(Promise.resolve("something")); //=> false
R.isPlainObject(new Date()); //=> false
R.isPlainObject(new Error("error")); //=> false
R.isPlainObject("somethingElse"); //=> false
R.isPlainObject(null); //=> false
[isPromise是否是Promise]
用于检查传递的参数是否是Promise,并相应地缩小其类型
用法:
R.isPromise(data)
例子:
R.isPromise(Promise.resolve(5)) //=> true
R.isPromise(Promise.reject(5)) //=> true
R.isPromise('somethingElse') //=> false
[isString是否是字符串]
用于检查传递的参数是否是字符串,并相应地缩小其类型
用法:
R.isString(data)
例子:
R.isString('string') //=> true
R.isString(1) //=> false
[isTruthy是否是truthy]
用于检查传递的参数是否是truthy,并相应地缩小其类型
用法:
R.isTruthy(data)
例子:
R.isTruthy('somethingElse') //=> true
R.isTruthy([]) //=> true
R.isTruthy(null) //=> false
R.isTruthy(undefined) //=> false
R.isTruthy(false) //=> false
R.isTruthy(0) //=> false
R.isTruthy('') //=> false
R.isTruthy(NaN) //=> false
[isSymbol是否是isSymbol]
用于检查传递的参数是否是Symbol,并相应地缩小其类型
用法:
R.isSymbol(data)
例子:
R.isSymbol(Symbol("foo")); //=> true
R.isSymbol(1); //=> false