reduce()是一个数组方法,平时不怎么用到,所以每次使用就忘了具体怎么用,总结一下,加深印象
1 语法
arr.reduce(function(prev,cur,index,arr){
…
}, init);
其中,
arr 表示原数组;
prev 表示上一次调用回调时的返回值,或者初始值 init;
cur 表示当前正在处理的数组元素;
index 表示当前正在处理的数组元素的索引,若提供 init 值,则索引为0,否则索引为1;
init 表示初始值。
看起来很复杂,其实常用的参数只有两个:prev 和 cur。
2 实例
定义一个数组
const arr = [3, 9, 4, 2, 0, 9]
使用reduc解决一下问题
(1) 求数组各项之和(经典)
const sum = arr.reduce(function (prev, cur) {
return prev + cur
}, 0)
传入了初始值0,所以prev的值为0, cur值为数组第一项3,相加之后3作为下一轮prev值,继续与数组下一项相加,直到加完数组所有项,最后返回和
(2) 求数组项最大值
const max = arr.reduce(function (prev, cur) {
reture Math.max(prev, cur)
})
没有传如初始值,开始时prev是数组的第一项3, cur的值是第二项9,求两项最大值进入下一轮求最大值
(3) 数组去重
const newArr = arr.reduce(function (prev, cur) {
prev.indexOf(cur) === -1 && prev.push(cur)
return prev
}, [])
将prev初始化为[],判断原数组的第一项是否在prev数组中,如果不存在则push进prev中
…对数组每一项处理之后, 返回prev这个数组
进阶使用
(4) 对象数组中使用
输出 “大哥、二哥和三哥”
const objArr = [{name: ‘大哥’}, {name: ‘二哥’}, {name: ‘三哥’}]
const res = objArr.reduce((prev, cur, index, arr) => {
if (index === 0) {
return cur.name
}
else if (index === arr.length -1) {
return prev + ‘和’ + cur.name
}
else {
return prev + ‘、’ + cur.name
}
}, ‘’)
(5) 求字符串中字母出现次数
const str = ‘akakabcbcabcdbdbd’
const res = str.split(’’).reduce((counter, cur) => {
counter[cur] ? counter[cur]++ : counter[cur] = 1
return counter
}, {})
(6) 数组转数组
const arr = [2,3,4,5]
const newArr = arr.reduce((prev, cur) => {
prev.push(cur * cur)
return prev
}, [])
(7) 数组转对象
const arr = [{name: ‘技术’, id: 1}, {name: ‘设计’, id: 2}]
const newArr = arr.reduce(function (prev, cur) => {
prev[cur.id] = cur
return prev
}, {})
高级用法
(8) 多维的叠加执行操作
加权求成绩
var result = [
{ subject: ‘math’, score: 88 },
{ subject: ‘chinese’, score: 95 },
{ subject: ‘english’, score: 80 }
];
var dis = {
math: 0.5,
chinese: 0.3,
english: 0.2
};
var res = result.reduce((accumulator, cur) => dis[cur.subject] * cur.score + accumulator, 0);
(9) 商品对应不同国家汇率不同,求总价格
var prices = [{price: 23}, {price: 45}, {price: 56}];
var rates = {
us: ‘6.5’,
eu: ‘7.5’,
};
var initialState = {usTotal:0, euTotal: 0};
var res = prices.reduce((accumulator, cur1) => Object.keys(rates).reduce((prev2, cur2) => {
console.log(accumulator, cur1, prev2, cur2);
accumulator[${cur2}Total
] += cur1.price * rates[cur2];
return accumulator;
}, {}), initialState);
var manageReducers = function() {
return function(state, item) {
return Object.keys(rates).reduce((nextState, key) => {
state[${key}Total
] += item.price * rates[key];
return state;
}, {});
}
};
var res1= prices.reduce(manageReducers(), initialState);
(10)flat 扁平一个二维数组
var arr = [[1, 2, 8], [3, 4, 9], [5, 6, 10]];
var res = arr.reduce((x, y) => x.concat(y), []);
(11) 数组对象去重
const hash = {};
chatlists = chatlists.reduce((obj, next: Object) => {
const hashId = ${next.topic}_${next.stream_id}
;
if (!hash[hashId]) {
hash[${next.topic}_${next.stream_id}
] = true;
obj.push(next);
}
return obj;
}, []);
(12) 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)))
}
3 相关方法
(1) reduceRight()
用法与reduce一样,遍历顺序相反,从最后一项开始,遍历到第一项
(2) forEach(), map(),every(),some(), filter()
一、forEach(),用于遍历数组,无返回值
二、map(),用于遍历数组,返回处理之后的新数组
三、every(),用于判断数组中的每一项元素是否都满足条件,返回一个布尔值
四、some(),用于判断数组中的是否存在满足条件的元素,返回一个布尔值
五、filter(),用于筛选数组中满足条件的元素,返回一个筛选后的新数组
// 只传一个匿名函数
arr.forEach(function(item,index,array){
console.log(this); // window
});
// 传两个参数
arr.forEach(function(item,index,array){
console.log(this); // [1, -2, 3, 4, -5]
},arr);
4 总结:
① forEach()无返回值,map()和filter()返回新数组,every()和some()返回布尔值
② 匿名函数中this指向默认为window,可通过传第二参数来更改之
③ 五种遍历方法均为ES5方法,IE8及其以下浏览器均不兼容。
reduce是数组归并方法, forEach()、map()、filter()是迭代方法, 它们都可以进行遍历,但是reduce()可以同时将前面数组项遍历产生的结果 与 当前遍历项进行运算,这是其他迭代方法所做不到的
【Array.prototype.keys()】 不用循环生成顺序数组
The keys() method returns a new Array Iterator object that contains the keys for each index in the array.
Iterator 返回索引
在分页组件中需要确定页码,于是需要生成一个在某个区间里的连续数值的数组。
用ES5的方法只能是循环输入了
function fn (start, end){
for(let i = 0, j = start; i< end - start; i++){
//…
}
}
不过刚刚突然想到一个不用循环的方法:
/**
- 生成一个从 start 到 end 的连续数组
- @param start
- @param end
*/
function generateArray (start, end) {
return Array.from(new Array(end + 1).keys()).slice(start)
}
4 总结
常用于转换数据结构
arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])注意:回调函数里的第一个参数是accumulator,表示累加器。
其他应用场景
1.求数组中所有元素的值的和
2.在对象数组中,求每个对象的指定属性值的和。
3.将二维数组中的每个子数组元素进行合并,最终将该二维数组转换为一维数组。
4.将数组中每个元素(重复)出现的次数进行统计,最后将结果以对象的形式输出。
5.根据指定属性,对对象数组中的对象进行分组。
6.结合spread运算符(三点运算符"…")一起使用
7.数组元素的去重
8.遍历数组,同时对符合条件的数组元素进行操作。
9.将promise的链式操作,按照顺序执行。 对多个promise链式操作进行同步顺序执行,这就对异步的嵌套执行,提供了reduce的解决方案,除了使用async/await语法外,这个在实际项目中也可以用一下。
10.开启由多个函数组成的管道
11.用reduce模拟数组的map函数