JS数组的reduce方法(续)

85 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 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]