# 万金油reduce方法的使用场景
在有关整理数组方法的文章中提及到reduce()方法的使用,在数组方法中reduce()算是一个比较复杂的方法了。其功能也很强大,有很多的使用场景,算是一个万金油方法。这么好的方法怎么能不用起来呢,这篇文章我整理并总结了reduce()方法的多种使用场景,希望后期能灵活的将其运用在项目中。

# 一、reduce()的用法
在正式了解reduce()方法的使用场景之前,先来回顾一下该方法的基本使用。我在网上找了一张图片我觉得可以十分贴切的描绘reduce()方法的作用~

- 作用:
reduce()方法将数组的所有元素按照给定的方式计算为一个值(从左到右) - 传参:array.reduce(callback(accumulator, currentValue, currentIndex, arr), initialValue)
- 参数说明:
reduce()方法接收两个参数分别是:一个回调函数callback,和一个initialValue做为第一次调用callback函数时第一个参数的值,如果没有提供初始值则使用数组的第一个元素。在callback函数中包含四个参数accumulator:累计器累计回调的返回值; 它是上一次调用回调时返回的累积值,如果没有给定initialValue参数时初始值是数组第一个值,后面会赋值为每次循环返回的值currentValue:数组中正在处理的元素,没有给定initialValue参数时,初始值默认是数组第二个值,后面依次第三个...到最后一个currentIndex:数组中正在处理的元素索引值array:调用reduce()方法的原数组
- 其内部的运行可以查看MDN官方文档,对reduce()方法的运行流程有详细的描述,这里就不赘述了
# 二、 使用场景
为了可以更好的展示如何在真实的开发场景中使用到reduce()方法,这里用一段开发中最常见的对象数组来对各个使用场景进行举例。
const members = [
{id: '1', name: 'Mark', age: 20},
{id: '2', name: 'Jane', age: 25},
{id: '3', name: 'Wendy', age: 18},
{id: '4', name: 'Alice', age: 20},
{id: '5', name: 'Mino', age: 32},
{id: '6', name: 'Sandy', age: 32},
]
# 1. 累加
需求:求所有成员的平均年龄
// 求得所有成员的总年龄
const ageSum = members.reduce((acc, cur) => acc + cur.age, 0)
const averageAge = ageSum / members.length
console.log(`平均年龄:${averageAge}`) // 平均年龄:24.5
# 2. 最值
需求:求所有成员中年龄最大和最小值
function getMaxAge(arr) {
const maxAgeMember = arr.reduce((acc, cur) => acc.age > cur.age ? acc : cur)
return maxAgeMember.age
}
console.log(`最大年龄:${getMaxAge(members)}`) // 最大年龄:32
function getMinAge(arr) {
const minAgeMember = arr.reduce((acc, cur) => acc.age < cur.age ? acc : cur)
return minAgeMember.age
}
console.log(`最小年龄:${getMinAge(members)}`) // 最大年龄:18
# 3. 筛选
需求:获取年龄最大值的成员信息
// 上面已经定义了获取最大年龄的方法
const maxAge = getMaxAge(members)
function getMaxAgeMerber(arr, age) {
return arr.reduce((acc, cur) => {
if (cur.age === age) {
acc.push(cur)
}
return acc
}, [])
}
console.log('最大年龄成员: ', getMaxAgeMerber(members, maxAge))

# 4. 判断
需求1:判断成员中有没有小于20岁的成员(替代了Array.prototype.some()方法)
const isLessThan20 = members.reduce((acc, cur) => acc || cur.age > 20, false)
console.log(`是否有小于20岁的成员:${isLessThan20}`) // true
需求2:判断是不是所有的成员都大于18岁(替代了Array.prototype.every()方法)
const allMoreThan18 = members.reduce((acc, cur) => acc && cur.age > 18, true)
console.log(`是否所有成员大于18岁:${allMoreThan18}`) // false
# 5. 数组转对象
需求:将members数组转换成以成员id为属性的对象结构
function arrToObj(arr, property) {
return arr.reduce((acc, cur) => {
const key = cur[property]
acc[key] = cur
return acc
}, {})
}
console.log(arrToObj(members, 'id'))

# 6. 出现次数
需求:统计成员中每个年龄的出现次数
const occurrences = members.reduce((acc, cur) => {
let key = cur.age
key in acc ? acc[key]++ : acc[key] = 1
return acc
}, {})
console.log(occurrences) // {18: 1, 20: 2, 25: 1, 32: 2}
# 7. 分类
需求:将成员按照不同年龄进行分类
const groupByAge = members.reduce((acc, cur) => {
let key = cur.age
if (!acc[key]) {
acc[key] = []
}
acc[key].push(cur)
return acc
}, {})
console.log(groupByAge)
// {
// 18: [{id: '3', name: 'Wendy', age: 18}],
// 20: [
// {id: '1', name: 'Mark', age: 20},
// {id: '4', name: 'Alice', age: 20}
// ],
// 25: [{id: '2', name: 'Jane', age: 25}],
// 32: [
// {id: '5', name: 'Mino', age: 32},
// {id: '6', name: 'Sandy', age: 32},
// ]
// }
# 三、其他使用场景
# 1. 数组扁平化
结合reduce()方法和递归操作,可以用于扁平化数组
function flatArr(arr) {
return Array.isArray(arr) ?
arr.reduce((acc, cur) => [...acc, ...flatArr(cur)], []) : [arr]
}
const arr = [1, [2, [3, 4]]
console.log(flatArr(arr)) // [1, 2, 3, 4]
# 2. 数组去重
function unique(arr) {
return arr.reduce((acc, cur) => acc.includes(cur) ? acc : [...acc, cur], [])
}
const arr = [1, 3, 5, 1, 9]
console.log(unique(arr)) // [1, 3, 5, 9]
# 3. 计算数组中每个元素出现的次数
function count(arr) {
return arr.reduce((acc, cur) => {
cur in acc ? acc[cur]++ : acc[cur] = 1
return acc
}, {})
}
const arr = ['apple', 'orange', 'apple', 'mango', 'mango']
console.log(count(arr)) // {apple: 2, orange: 1, mango: 2}