reduce的使用(最详解)

用途:用于对数组进行条件统计,条件求和,筛选求和。

  • 一个 “reducer” 函数,包含四个参数:

    • previousValue:上一次调用 callbackFn 时的返回值。在第一次调用时,若指定了初始值 initialValue,其值则为 initialValue,否则为数组索引为 0 的元素 array[0]

    • currentValue:数组中正在处理的元素。在第一次调用时,若指定了初始值 initialValue,其值则为数组索引为 0 的元素 array[0],否则为 array[1]

    • currentIndex:数组中正在处理的元素的索引。若指定了初始值 initialValue,则起始索引号为 0,否则从索引 1 起始。

    • array:用于遍历的数组。

  • initialValue 可选:

作为第一次调用 callback 函数时参数 previousValue 的值。若指定了初始值 initialValue,则 currentValue 则将使用数组第一个元素;否则 previousValue 将使用数组第一个元素,而 currentValue 将使用数组第二个元素。

  • 返回值:

使用 “reducer” 回调函数遍历整个数组后的结果。

示例:

  1. 求数组所有值的和

    let sum = [0, 1, 2, 3].reduce(function (previousValue, currentValue) {
      return previousValue + currentValue
    }, 0)
    // sum is 6

    写成箭头函数

    let total = [ 0, 1, 2, 3 ].reduce(
      ( previousValue, currentValue ) => previousValue + currentValue,
      0
    )
  2. 累加对象数组里的值

    要进行累加对象数组中的值,必须提供 initialValue,以便各个 item 正确通过你的函数。

    let initialValue = 0
    let sum = [{x: 1}, {x: 2}, {x: 3}].reduce(function (previousValue, currentValue) {
        return previousValue + currentValue.x
    }, initialValue)
    ​
    console.log(sum) // logs 6

    写成箭头函数

    let initialValue = 0
    let sum = [{x: 1}, {x: 2}, {x: 3}].reduce(
        (previousValue, currentValue) => previousValue + currentValue.x
        , initialValue
    )
    ​
    console.log(sum) // logs 6
  3. 将二维数组转为一维数组

    concat() 用于连接两个或多个数组

    let flattened = [[0, 1], [2, 3], [4, 5]].reduce(
      function(previousValue, currentValue) {
        return previousValue.concat(currentValue)
      },
      []
    )
    // flattened is [0, 1, 2, 3, 4, 5]

    写成箭头函数

    let flattened = [[0, 1], [2, 3], [4, 5]].reduce(
      ( previousValue, currentValue ) => previousValue.concat(currentValue),
      []
    )
  4. 计算数组中每个元素出现的次数

    let names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice']
    ​
    let countedNames = names.reduce(function (allNames, name) {
      if (name in allNames) {
        allNames[name]++
      }
      else {
        allNames[name] = 1
      }
      return allNames
    }, {})
    // countedNames is:
    // { 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 }
  5. 按属性对 object 分类

    let people = [
      { name: 'Alice', age: 21 },
      { name: 'Max', age: 20 },
      { name: 'Jane', age: 20 }
    ];
    ​
    function groupBy(objectArray, property) {
      return objectArray.reduce(function (acc, obj) {
        let key = obj[property]
        if (!acc[key]) {
          acc[key] = []
        }
        acc[key].push(obj)
        return acc
      }, {})
    }
    ​
    let groupedPeople = groupBy(people, 'age')
    // groupedPeople is:
    // {
    //   20: [
    //     { name: 'Max', age: 20 },
    //     { name: 'Jane', age: 20 }
    //   ],
    //   21: [{ name: 'Alice', age: 21 }]
    // }
  6. 使用扩展运算符和 initialValue 绑定包含在对象数组中的数组

    // friends - an array of objects
    // where object field "books" is a list of favorite books
    let friends = [{
      name: 'Anna',
      books: ['Bible', 'Harry Potter'],
      age: 21
    }, {
      name: 'Bob',
      books: ['War and peace', 'Romeo and Juliet'],
      age: 26
    }, {
      name: 'Alice',
      books: ['The Lord of the Rings', 'The Shining'],
      age: 18
    }]
    ​
    // allbooks - list which will contain all friends' books +
    // additional list contained in initialValue
    let allbooks = friends.reduce(function(previousValue, currentValue) {
      return [...previousValue, ...currentValue.books]
    }, ['Alphabet'])
    ​
    // allbooks = [
    //   'Alphabet', 'Bible', 'Harry Potter', 'War and peace',
    //   'Romeo and Juliet', 'The Lord of the Rings',
    //   'The Shining'
    // ]
  7. 数组去重

    备注: 如果你正在使用一个可以兼容Set 和 Array.from() 的环境,你可以使用let arrayWithNoDuplicates = Array.from(new Set(myArray)) 来获得一个相同元素被移除的数组。

    let myArray = ['a', 'b', 'a', 'b', 'c', 'e', 'e', 'c', 'd', 'd', 'd', 'd']
    let myArrayWithNoDuplicates = myArray.reduce(function (previousValue, currentValue) {
      if (previousValue.indexOf(currentValue) === -1) {
        previousValue.push(currentValue)
      }
      return previousValue
    }, [])
    ​
    console.log(myArrayWithNoDuplicates)
  8. 使用 .reduce() 替换 .filter().map()

    使用 Array.filter() 和 Array.map() 会遍历数组两次,而使用具有相同效果的 Array.reduce() 只需要遍历一次,这样做更加高效。(如果你喜欢 for 循环,你可用使用 Array.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]
  9. 按顺序执行 Promise

    /**
     * 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
  10. 使用函数组合实现管道

    // 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) // 256
    multiply24(10) // 240
  11. 使用 reduce 实现 map

    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]

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值