js中的reduce用法

350 阅读3分钟
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方法
    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
    
    对比一下,是不是,reduce方法很简单?

(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。