以前一直不怎么用reduce,用过之后觉得这个方法非常好,能优雅的解决一些困扰人的结果运算, rxjs中很多地方都有scan(跟reduce类似)身影
MDN文档
js reduce的一些使用
reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终为一个值,是ES5中新增的又一个数组逐项处理方法,那reduce方法跟foreach、map等数组方法又有啥区别呢。
arr.reduce(callback[, initialValue]) — More From MDN
callback(一个在数组中每一项上调用的函数,接受四个函数:)
previousValue(上一次调用回调函数时的返回值,或者初始值)
currentValue(当前正在处理的数组元素)
currentIndex(当前正在处理的数组元素下标)
array(调用reduce()方法的数组)
initialValue(可选的初始值。作为第一次调用回调函数时传给previousValue的值)
另一些高级用法:https://www.jb51.net/article/132324.htm
1、求和
var arr=[1,2,3,4];
var total=arr.reduce((pre,cur)=>{
return pre+cur;
});
根据定义还可以传初始值
var total=arr.reduce((pre,cur)=>pre+cur,10);
2、计算对象数组的某字段最大值对象
var objArr=[
{"type":"java","count":10},
{"type":"c++","count":20},
{"type":"javascript","count":100},
{"type":"c#","count":10},
{"type":"python","count":30}
]
let maxObj=objArr.reduce((pre,cur)=>{
return pre.count>cur?pre:cur;
});
//返回 {"type":"javascript","count":100}
3、特殊处理
以上面的对象数组为例, 要求返回 var languages='java,c++,javascript,c# 和 python';
var languages=objArr.reduce((pre,cur,index,arr)=>{
if(index===0){ //第一项
return pre+cur.type;
}else if(index=== arr.length-1){ //最后一项
return pre+' 和 '+cur.type;
}
return pre+','+cur.type
},''); //初始值是空字符串
4、一串字符串中每个字母出现的次数?
var arrString = 'abcdaabddcca';
arrString.split('').reduce(function (prev, curr) {
prev[curr] ? prev[curr]++ : prev[curr] = 1;
return prev;
}, []);
// [a: 4, b: 2, c: 3, d: 3]
//某个数在数组中出现的次数
const countOccurrences = (arr, value) => arr.reduce((a, v) => v === value ? a + 1 : a + 0, 0);
countOccurrences([1, 2, 3, 2, 2, 5, 1], 1);
//如果初始值换成对象
var arrString = 'abcdaabddcca';
arrString.split('').reduce(function (prev, curr) {
prev[curr] ? prev[curr]++ : prev[curr] = 1;
return prev;
}, {});
{a: 4, b: 2, c: 3, d: 3}
5、字母游戏
const anagrams = str => {
if (str.length <= 2) { //如果字符串的长度小于等于2
return str.length === 2 ? [str, str[1] + str[0]] : str;
}
return str.split("").reduce((acc, letter, i) => {
return acc.concat(anagrams(str.slice(0, i) + str.slice(i + 1)).map(val => letter + val));
}, []);
}
anagrams("abc"); // 结果会是什么呢?
6、计算数组对象重复个数 (如下:如果code相同,则数量+1)
var list = [
{"date":'2018-08-01',"time":'11:21:20',"code":'11111',"name":'民乐工业园1栋东山口民乐工业',"lng":'112.203909',"lat":'31.021737',"img":'http://192.168.0.12:8080/images/usr/'},
{"date":'2018-08-02',"time":'11:21:20',"code":'11112',"name":'民乐工业园1栋东山口民乐工业',"lng":'112.202104',"lat":'31.023602',"img":'http://192.168.0.12:8080/images/usr/'},
{"date":'2018-08-02',"time":'11:21:20',"code":'11112',"name":'民乐工业园1栋东山口民乐工业',"lng":'112.202104',"lat":'31.023602',"img":'http://192.168.0.12:8080/images/usr/'},
{"date":'2018-08-03',"time":'11:21:20',"code":'11113',"name":'民乐工业园1栋东山口民乐工业',"lng":'112.203909',"lat":'',"img":'http://192.168.0.12:8080/images/usr/'}
];
let obj={}; //通过一个对象来过渡
var filterArr=list.reduce((pre,cur)=>{
if(obj[cur.code]){
obj[cur.code]++;
pre.find(c=>c.code==cur.code).count++;
}else{
obj[cur.code]=1;
pre.push(Object.assign({},{count:obj[cur.code]},cur));
}
return pre;
},[]);
console.log(filterArr);
7、分组
const groupBy = (arr, func) =>
arr.map(typeof func === 'function' ? func : val => val[func]).reduce((acc, val, i) => {
acc[val] = (acc[val] || []).concat(arr[i]);
return acc;
}, {});
groupBy([6.1, 4.2, 6.3], Math.floor);
groupBy(['one', 'two', 'three'], 'length');