「前端每日一问(13)」说一下数组 reduce 方法的一些用法

414 阅读3分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

本题难度:⭐ ⭐

答:

reduce() 方法对数组中的每个元素执行一个由开发者提供的 reducer 函数(升序执行),将其结果汇总为单个返回值。

用好 reduce,可以很大程度上减少代码量。

语法:

arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])

一些常用的用法:

数组里所有值求和:

const arr = [1, 2, 3]
const sum = arr.reduce((acc, cur) => acc + cur)
console.log(sum)  // 6

查找数组中最大值

const arr = [0, 1, 2, 3, 4, 5]
const max = arr.reduce((acc, cur) => Math.max(acc, cur))
console.log(max) // 5

累加对象数组的值:

const arr = [{ x: 1 }, { x: 2 }, { x: 3 }]
const sum = arr.reduce((acc, cur) => acc + cur.x, 0)
console.log(sum) // 6

将二维数组转化为一维数组:

const arr = [[0, 1], [2, 3], [4, 5]]
const res = arr.reduce((acc, cur) => acc.concat(cur), [])
console.log(res) // [0, 1, 2, 3, 4, 5]

不过不如直接用数组 flat 方法简洁。

const arr = [[0, 1], [2, 3], [4, 5]]
const res = arr.flat() // [0, 1, 2, 3, 4, 5]

计算数组中每个元素出现的次数:

const arr = ['hello', 'world', 'lin', 'hello', 'lin']

const obj = arr.reduce((acc, cur) => {
  if (cur in acc) {
    acc[cur]++
  } else {
    acc[cur] = 1
  }
  return acc
}, {})
console.log(obj) // { hello: 2, world: 1, lin: 2 }

按属性对 Object 分类

const people = [
  { name: 'Alice', age: 21 },
  { name: 'Max', age: 20 },
  { name: 'Jane', age: 20 }
]

function groupBy (objectArray, property) {
  return objectArray.reduce((acc, obj) => {
    const key = obj[property]
    if (!acc[key]) {
      acc[key] = []
    }
    acc[key].push(obj)
    return acc
  }, {})
}

const groupedPeople = groupBy(people, 'age')
console.log(groupedPeople)
// {
//   20: [
//     { name: 'Max', age: 20 },
//     { name: 'Jane', age: 20 }
//   ],
//   21: [{ name: 'Alice', age: 21 }]
// }

使用扩展运算符和初始值绑定包含在对象数组中的数组

// friends - 对象数组
// where object field "books" - list of favorite books
const 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
const allbooks = friends.reduce((acc, curr) => {
  return [...acc, ...curr.books]
}, ['Alphabet'])
console.log(allbooks)
// allbooks = [
//   'Alphabet', 'Bible', 'Harry Potter', 'War and peace',
//   'Romeo and Juliet', 'The Lord of the Rings',
//   'The Shining'
// ]

数组去重

const arr = ['a', 'b', 'a', 'b', 'c', 'e', 'e', 'c', 'd', 'd', 'd', 'd']
const res = arr.reduce((acc, cur) => {
  if (acc.indexOf(cur) === -1) {
    acc.push(cur)
  }
  return acc
}, [])

console.log(res) // ['a', 'b', 'c', 'e', 'd']

不过不如用 Set 去重简洁。

const arr = ['a', 'b', 'a', 'b', 'c', 'e', 'e', 'c', 'd', 'd', 'd', 'd']
const res = Array.from(new Set(arr)) // ['a', 'b', 'c', 'e', 'd']

串行执行 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(
    (acc, cur) => acc.then(cur),
    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

扩展阅读:25个你不得不知道的数组reduce高级用法

结尾

如果我的文章对你有帮助,你的👍就是对我最大的支持^_^

我是阿林,输出洞见技术,再会!

上一篇:

「前端每日一问(12)」JavaScript 中数组常用方法有哪些?

下一篇:

「前端每日一问(14)」JavaScript 中如何中断 forEach 循环?