一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第5天,点击查看活动详情
上篇文章我们讲了reduce
的基本用法,这篇文章讲一讲reduce
的进阶用法
数组去重
let arr1 = ['a', 'b', 'a', 'b', 'c', 'e', 'e', 'c', 'd', 'd', 'd', 'd']
let arr2 = arr1.reduce(function (pre, cur) {
if (pre.indexOf(cur) === -1) {
pre.push(cur)
}
return pre
}, [])
console.log(arr2)
上面可以看到,利用传进去的init
初始值为空数组,每次判断空数组中存不存在当前元素cur
,不存在就往pre
里面push
进去,存在就下一个,最后返回最终将不包含重复元素的数组
使用 .reduce() 替换 .filter().map()
使用 Array.filter()
和 Array.map()
会遍历数组两次,而使用具有相同效果的 Array.reduce()
只需要遍历一次,这样做更加高效。
下面就是筛选出数组中大于0的数字再乘二输出,也可以使用foreach
方法对每个选项进行先判断后乘法的操作
const numbers = [-5, 6, 2, 0];
const doubledPositiveNumbers = numbers.reduce((previousValue, currentValue) => {
if (currentValue > 0) {
const doubled = currentValue * 2;
previousValue.push(doubled);
}
return previousValue;
}, []);
console.log(doubledPositiveNumbers); // [12, 4]
按顺序运行 Promise
当我们需要将数组中的异步函数按照数组的顺序运行的,得出最终结果的时候,可以使用reduce进行处理
/**
* Runs promises from array of functions that can return promises
* in chained manner
*
* @param {array} arr - promise arr
* @return {Object} promise object
*/
function runPromiseInSequence(arr, input) {
return arr.reduce(
(promiseChain, currentFunction) => promiseChain.then(currentFunction),
Promise.resolve(input)
)
}
// promise function 1
function p1(a) {
return new Promise((resolve, reject) => {
resolve(a * 5)
})
}
// promise function 2
function p2(a) {
return new Promise((resolve, reject) => {
resolve(a * 2)
})
}
// function 3 - will be wrapped in a resolved promise by .then()
function f3(a) {
return a * 3
}
// promise function 4
function p4(a) {
return new Promise((resolve, reject) => {
resolve(a * 4)
})
}
const promiseArr = [p1, p2, f3, p4]
runPromiseInSequence(promiseArr, 10)
.then(console.log) // 1200
使用函数组合实现管道
下面这个例子就是利用reduce累加的特性,实现将传入的数字进行一系列处理之后返回总和,我们在日常的业务中可以这样使用来减轻我们的心智负担,提高代码的可迭代性
// Building-blocks to use for composition
const double = x => x + x
const triple = x => 3 * x
const quadruple = x => 4 * x
// Function composition enabling pipe functionality
const pipe = (...functions) => initialValue => functions.reduce(
(acc, fn) => fn(acc),
initialValue
)
// Composed functions for multiplication of specific values
const multiply6 = pipe(double, triple)
const multiply9 = pipe(triple, triple)
const multiply16 = pipe(quadruple, quadruple)
const multiply24 = pipe(double, triple, quadruple)
// Usage
multiply6(6) // 36
multiply9(9) // 81
multiply16(16) // 25600
multiply24(10) // 240
使用 reduce 实现 map
实现这个方法可以帮助你更好的理解reduce函数,日常中map还是不要用reduce代替的好(笑)
if (!Array.prototype.mapUsingReduce) {
Array.prototype.mapUsingReduce = function(callback, initialValue) {
return this.reduce(function(mappedArray, currentValue, currentIndex, array) {
mappedArray[currentIndex] = callback.call(initialValue, currentValue, currentIndex, array)
return mappedArray
}, [])
}
}
[1, 2, , 3].mapUsingReduce(
(currentValue, currentIndex, array) => currentValue + currentIndex + array.length
) // [5, 7, , 10]