js Array reduce

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函数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值