1,基本概念
-
reduce() 方法接收一个函数作为累加器(accumulator),数组中的每个值(从左到右)开始缩减,最终为一个值。
-
reduce 为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元素,接受四个参数:初始值(或者上一次回调函数的返回值),当前元素值,当前索引,调用 reduce 的数组。
-
语法:
arr.reduce(callback,[initialValue])(1) callback(执行数组中每个值的函数,包括4个参数)
- preVal(上一次调用回调函数返回的值,或者是自定义的初始值(initVal))
- currentVal(数组中当前被处理的元素)
- index(当前元素的索引值)
- array(需要操作的数组)
(2) initVal(作为第一次调用callback的第一个参数)
2,使用场景
- 数组的累加求和
- 数组的累乘求积
- 数组去重
- 计算数组中每个元素出现的次数
- 将对维数组(大于等于2)转为一维数组
- 对象里的属性求和
下面我们就对以上六种场景使用reduce方法,做代码分析。
(1)之前,我们在对数组做累加求和的时候,会想到的操作:
- 定义一个变量,用于计算结果
- 循环遍历数组,不管是for,for...in ,map,forEach,for...of
- 比如,我们就列举一种常见的:map方法
现在我们用reduce方法累加求和。let arr = [1,2,3,5,6] let sum = 0; arr.map(v=>sum += v) console.log(sum) // 17对比一下,是不是,reduce方法很简单?let arr = [1,2,3,5,6] let sum = arr.reduce((preVal,currentVal)=>preVal+currentVal) console.log(sum) // 17
(2)之前,我们在对数组做累加求和的时候,会想到的操作:和上面的累加求和思想一样。
现在我们用reduce方法累乘求积
let arr = [1,2,3,5,6]
let sum = arr.reduce((preVal,currentVal)=>preVal*currentVal)
console.log(sum) // 180
(3)数组去重
之前,我们可能这样操作:
- 最简单方法(indexOf方法)
- **实现思路:**新建一个数组,遍历要去重的数组,当值不在新数组的时候(indexOf 为 -1)就加入该新数组中;
function unique(arr){
let newArr = [];
for(let i = 0; i < arr.length; i++){
if(newArr.indexOf(arr[i]) == -1){
newArr.push(arr[i])
}
}
return newArr;
}
let arr = [1,2,3,4,5,1,2,5,6];
let newArr = unique(arr);
console.log(newArr); //[1,2,3,4,5,6]
- 优化遍历去重
- 实现思路:双层循环,外循环表示从0到arr.length,内循环表示从i+1到arr.length,将没重复的右边值放 入新数组。(检测到有重复值时终止当前循环同时进入外层循环的下一轮判断)。
function unique(arr){
let newArr = [];
for(let i = 0; i < arr.length; i++){
for(let j = i+1; j < arr.length; j++){
if(arr[i] == arr[j]){
++i;
}
}
newArr.push(arr[i]);
}
return newArr;
}
let arr = [1,2,3,4,5,3,2,1,5,7];
let newArr = unique(arr);
console.log(newArr); //[1,2,3,4,5,7]
- 对象属性不能相同的特点去重
-
实现思路:
1,创建一个新的数组存放结果
2,创建一个空对象
3,for循环时,每次取出一个元素与对象进行对比,如果这个元素不重复,则把它存放到结果数组中,同时把这个元素的内容作为对象的一个属性,并赋值为1,存入到第2步建立的对象中。
function unique(arr){
let res = [];
let obj = {};
for(let i=0; i<arr.length; i++){
if( !obj[arr[i]] ){
obj[arr[i]] = 1;
res.push(arr[i]);
}
}
return res;
}
let arr = [1,2,3,4,5,3,2,1,5,7];
let res = unique(arr)
console.log(res );
- new Set()去重
let arr =[1,2,3,4,1,3,5,6,2]
let newArr = Array.from(new Set(arr))
console.log(newArr) // [1,2,3,4,5,6]
现在我们用reduce方法去重。(1)数组去重(2)数组对象去重。
//数组去重
let arr = [1,2,3,4,4,1]
let newArr = arr.reduce((pre,cur)=>{
if(!pre.includes(cur)){
return pre.concat(cur)
}else{
return pre
}
},[])
console.log(newArr);// [1, 2, 3, 4]
//数组对象去重
//需求:去除key值相等的对象。
var arr = [
{key: '01', value: '乐乐' }, {key: '02',value: '博博' },
{ key: '03', value: '淘淘' }, {key: '04',value: '哈哈'},
{key: '01', value: '乐乐' }
];
var obj = {};
arr = arr.reduce((pre, cur)=> {
obj[cur.key] ? '' : obj[cur.key] = true && pre.push(cur);
return pre;
}, []);
console.log(arr);
(4)计算数组中每个元素出现的次数
let names = ['tom', 'Bob', 'jack', 'jack', 'alice'];
let nameNum = names.reduce((pre,cur)=>{
if(cur in pre){
pre[cur]++
}else{
pre[cur] = 1
}
return pre
},{})
console.log(nameNum); //{tom: 1, Bob: 1, jack: 2, alice: 1}
(5)将对维数组(大于等于2)转为一维数组
<1>我们先将二维数组,转为一维数组
let arr = [[0, 1], [2, 3], [4, 5]]
let newArr = arr.reduce((pre,cur)=>{
return pre.concat(cur)
},[])
console.log(newArr); // [0, 1, 2, 3, 4, 5]
<2>再将多维数组,转为一维数组。这里我们用了一下递归
let arr = [[0, 1], [2, 3], [4,[5,6,7]]]
const newArr = arr=>{
return arr.reduce((pre,cur)=>pre.concat(Array.isArray(cur)?newArr(cur):cur),[])
}
console.log(newArr(arr)); //[0, 1, 2, 3, 4, 5, 6, 7]
(6)对象里的属性求和
let result = [
{
subject: 'math',
score: 10
},
{
subject: 'chinese',
score: 20
},
{
subject: 'english',
score: 30
}
];
let sum = result.reduce((prev, cur)=> {
return cur.score + prev;
}, 0);
console.log(sum) //60
3,总结
灵活使用reduce方法,不仅使得功能现实起来变得简单,而且使得代码非常简洁。保证了代码的可读性、可维护性。 多学一点js的高级语法,用最少的代码量实现想要的功能。Keep Learning。