JavaScript 之 reduce()的用法

378 阅读3分钟

首先,参考了这位大佬的总结,敲了一遍,收获很大。记录下来。跳转

背景:

之前是接触vue源码的时候,发现使用reduce的地方很多。当时也是在看别人分享,简单带过,发现很好用。简单研究后,很少用到。导致理解不深。今天碰到到使用场景,特意花时间研究了一番,可以说理解的很到位了。

语法

arr.reduce(function(prev,cur,index,arr){
    ...
}, init);

其中,
arr 表示原数组;
prev 表示上一次调用回调时的返回值,或者初始值 init;
cur 表示当前正在处理的数组元素;
index 表示当前正在处理的数组元素的索引,若提供 init 值,则索引为0,否则索引为1;
init 表示初始值。【这个初始值在很多技巧上要用到,要重点留意】

在实际使用当中,其实常用的参数只有两个:prev 和 cur。结合例子来分析一番。

实例

以下举的例子除了用reduce来实现,还有很多其他的方法。不过使用reduce有它独有的技巧性和方便。

1、求数组的和

方式一:

let arr = [3,4,5,6,9,2,4,6];
let sum = arr.reduce((pre,cur,index,arr)=>{
    // console.log('index:',index);
    // console.log('arr:',arr);
    return pre + cur;
})
console.log(sum);

方式二:

let sum = arr.reduce((pre,cur,index,arr)=>{
    // console.log('index:',index);
    // console.log('arr:',arr);
    return pre + cur;
},0)
console.log(sum);

注意:方式二,由于传入了初始值0,所以pre的初始值就是0,cur的值,就是数组的第一个值为3;如果不传初始值的话,就如方式一,这时,pre的值是3,cur的值是4;相加后为7,作为下一轮的pre的值,cur是5,依次类推下去。

2、求数组的最大值

方式一:

let arr = [1,4,5,6,9,2,4,6];
let max  =  arr.reduce((pre,cur)=>{
    return Math.max(pre,cur)
})
console.log(max);

方式二:

let max2 = arr.reduce((pre,cur)=>{
    return pre > cur ? pre:cur;
})
console.log('max2:',max2);

3、给数组去重

let newArr = arr.reduce((pre,cur)=>{
    pre.indexOf(cur) === -1 && pre.push(cur)
    return pre
},[])
console.log(newArr);

进阶用法

1.求字符串中字幕出现的次数

const str = 'sfhjasfjgfasjuwqrqadqeiqsajsdaiwqdaklldflas-cmxzmnha';
const res = str.split('').reduce((pre,cur)=>{
    pre[cur] ? pre[cur]++ : pre[cur] = 1;
    return pre
},{})
console.log('汇总次数:',res);

2.数组转数组

let arr1 = [2,3,4,5,6,7];
let newArr1 = arr1.reduce((pre,cur)=>{
    pre.push(cur*cur)
    return pre;
},[])
console.log('数组转数组:',newArr1);

3. 数组转对象

let streams = [{ name: '博士',id: 1},{ name:'硕士', id:2},{ name: '本科',id:3}];
let obj1 = streams.reduce((pre,cur)=>{
    pre[cur.id] = cur;
    return pre;
},{})
console.log('数组转对象:',obj1);

高级用法

1. 多维的叠加执行操作

例子:各科成绩占比不一样,求结果

const result = [
    { subject: 'math',score: 99},
    { subject: 'chinese',score:95},
    { subject: 'english',score:80},
];
const dis = {
    math: 0.5,
    chinese: 0.2,
    english: 0.4
};
let res2 = result.reduce((pre,cur)=>{
    return dis[cur.subject] * cur.score + pre
},0)
console.log('多维叠加:',res2);

加大难度:商品对应不同国家汇率不同,求价格

const prices = [{price: 23},{price: 45},{price:56}];
const rates = { us: '6.5', eu:'7.5'};
const initialState = { usTotal: 0, euTotal: 0};
const res3 = prices.reduce((pre1,cur1)=> Object.keys(rates).reduce((pre2,cur2)=>{
    pre1[`${cur2}Total`] += cur1.price * rates[cur2];
    return pre1;
},{}),initialState)
console.log(res3);

2、扁平一个二维数组

const arr4 = [ [1,2,3],[4,5,6],[7,8,9]];
const res4 = arr4.reduce((pre,cur)=>{
    return  pre.concat(cur)
},[])
console.log('扁平一个二维数组',res4);

多维数组扁平化

3、对象数组去重

const hash = {};
chatLists = chatLists.reduce((obj,next)=>{
    const hashId = `${next.topic}_${next.stream_id}`;
    if(!hash[hashId]){
        hash[`${next.topic}_${next.stream_id}`]=true;
        obj.push(next)
    }
    return obj;

},[])

4、compose函数

redux compose 源码实现

function compose(...funs){
    if(funs.length === 0){
        return arg => arg
    }
    if(funs.length === 1){
        return funs[0]
    }
    return funs.reduce((a,b)=>(...arg)=>a(b(...arg)))
}