个人觉得reduce方法可能是数组最有用的方法之一,数组其他迭代方法如forEach, map, filter, some, every的功能它都能做到。
reduce方法接受两个参数,第一个参数为一个函数,该函数接受4个参数:前一个值、当前值、当前值在数组中的索引、数组本身;第二个参数为可选的初始值,这个参数虽然是可选的,但是非常重要,后面会在例子中展示它的使用。
下面使用reduce来实现forEach, map, filter, some, every的功能:
let arr = [1, 2, 3, 4, 5]
//forEach
arr.reduce((pre, cur, index, self) => {
//以0作为初始值,第一次迭代时pre就是0
//cur就是每一次迭代的项
//我们可以对每一项来做一些操作
}, 0)
//map
let result = arr.reduce((pre, cur, index, self) => {
//实现每一项乘2
return pre.concat( cur * 2 )
}, [])
// [2, 4, 6, 8 , 10]
//filter
let result = arr.reduce((pre, cur, index, self) => {
//实现返回大于3的项
if ( cur > 3) {
return pre.concat(cur)
}
return pre
}, [])
//[4, 5]
//some every
//目前想到的方法是符合条件抛出异常,在捕获错误处重新赋值,实现得有点丑陋
let result;
try {
result = arr.reduce((pre, cur, index, self) => {
if(cur > 3) {
throw new Error('break')
}
}, 0)
} catch(error) {
if (error.message === 'break') {
result = true // or false
}
}
11.24更新实现some every功能:
//some
//判断是否有大于3的值
result = arr.reduce((pre, cur, index, self) => {
if(cur > 3) {
//有一个大于3
self.status = true
}
//没有匹配到的时候此时是undefined,通过!!转化为布尔值
return !!self.status
}, 0)
//every
//判断是否每个值都大于0
result = arr.reduce((pre, cur, index, self) => {
//有一个小于或等于0的值就为false
if(cur <= 0) {
self.status = false
}
//使用全等是因为还有undefined的情形
return self.status === false ? false : true
}, 0)
reduce的其他应用:
1)通过reduce数组去重
let arr = [1, 1, 2, 2 , 3, 4, 5]
let result = arr.reduce((pre, cur) => {
if (pre.includes(cur)) {
return pre
}
return pre.concat(cur)
}, [])
//[1, 2, 3, 4, 5]
2)求契波那切数列的第N项
function fibonacci(n) {
let arr = new Array(n+1).fill(1);
let newArr = arr.reduce((pre, cur, index, arr) => {
if (pre.length < 2) {
return pre.concat(cur)
} else {
let length = pre.length;
return pre.concat(pre[length-2] + pre[length-1])
}
}, [])
return newArr[n]
}
3)找出字符串中出现次数最多的字符
function findMostChar(str) {
//得到以字符为key,以其出现的次数为值的对象
let obj = Array.prototype.reduce.call(str, (pre, cur) => {
pre[cur] ? pre[cur]++ : (pre[cur] = 1)
return pre
}, {})
//根据字符出现次数倒序排序
let sortArr = Object.entries(obj).sort((a, b) => {
return b[1] - a[1]
})
//返回最大次数的项
return sortArr[0]
}
如有错误或者有其他更好的用法欢迎讨论