本篇文章参考以下博文
一、前言
最近在解决去重问题上,搜到一个使用 reduce 来进行去重的,几行代码解决了当数组元素是对象时,要求按照某一属性对数组中的对象进行去重的问题, reduce 这个方法感觉可以挖掘的东西还很多,写此文章记录总结一下,方便后面复习查看。
二、定义
reduce 的定义比较官方,一开始看的话很抽象,我们先记录在这里,等有初步认识后,在回来看。
reduce() 方法接收一个函数作为 累加器 ,数组中的每个值(从左到右)开始 缩减 ,最终计算为一个值。对空数组是不会执行回调函数的。
三、归并原理
reduce 是通过归并实现的一个操作数组的方法。使用方式如下:
array.reduce(callBack, init)
上面 reduce 接收两个参数,第一个是回调函数,用来进行一些计算之类的操作,第二个参数可选,是回调函数计算时的初始值。
这里说明一下,这个回调函数有两个必需参数, prev 和 current。
array.reduce(function(prev, current, curIndex, arr), init)
- prev:函数传进来的初始值或上一次回调的返回值
- current:数组中当前处理的元素值
- curIndex:当前元素索引
- arr:当前元素所属的数组本身
- init:传给回调函数的初始值
当不设置初始值 init 的时候, prev 是数组的第一个元素, current 是数组的第二个元素,这两个元素在回调函数中计算后,返回一个数值,然后 递归 。
在递归过程中,刚刚得出的计算值重新作为 新的 prev , 然后数组的第三个元素作为 current,进行计算,直到所有数据计算完成,递归结束。
上面流程图是没有初始值 init 的时候 ,大致可以描述一下 reduce 的工作原理。
当有 初始值 init 的情况下,首次执行是将 init 作为第一个 prev,将 a[0] 作为第一个 current 进行计算,后面类似。
四、案例
原理我们基本了解了,接下来看一下这个 reduce 有什么用,仅仅是给数组求和吗?
4.1 数组元素求和
let arr = [1, 2, 3];
let fn = (prev, current) => {
return prev + current;
}
let totle = arr.reduce(fn, 0);
4.2 计算数组某一元素出现的次数
let fn = (arr, value) => {
return arr.reduce((prev, current) => {
return current === value ? prev + 1 : prev
}, 0)
}
fn(arr, value)
4.3 合并二维数组
var red = [[0, 1], [2, 3], [4, 5]].reduce(function(prev, current) {
return prev.concat(current);
}, []);
4.4 数组中的元素是对象时去重
let arr = [{id: 123, name: 1}, {id: 123, name: 2}, {id: 123, name: 3}]
let newobj = {};
arr = arr .reduce((prev, current) => {
newobj[current.id] ? '' : newobj[current.id] = true && prev.push(current);
return prev
}, [])
//arr[{id: 123, name: 1}]
需要注意的是,上面去重是按照数组中对象的 id 属性去重的,如果要去重别的属性,需要手动修改。
该方法原理是把 id 的数值作为对象的属性,然后递归判断是否存在 id 值相同的。
4.5 计算数组中最大值最小值
const readings = [1, 2, 3, 5, 7, 4, 9];
function minMaxReducer(prev, current) {
return {
min: Math.min(prev.min, current),
max: Math.max(prev.max, current),
};
}
const initMinMax = {
min: Number.MIN_VALUE,
max: Number.MAX_VALUE,
};
const minMax = readings.reduce(minMaxReducer, initMinMax);
console.log(minMax);
// {minReading: 1, maxReading: 9}