用reduce对比两个数组的差异

假如有两个数组pre、cur,比较两个数组之间的差异,比如在pre中但不在cur数组中,在cur数组中不在pre数组中,这个时候会想到用filter过滤返回一个新的数组,filter的条件为pre数组是否cur数组的某一项,可以写成:

1
2
3
4
5
6
var pre = [1, 2, 3, 4, 5]
var current = [3, 4, 5, 6, 7]
var diff = pre.filter(item => !current.includes(item))
console.log(diff)

=> [1,2]

大佬说这样的时间负责度太高了,于是乎亮出大招:

1
2
3
4
5
6
7
8
9
var bMap = current.reduce((map, i) => {
map[i] = 1
return map
}, {})

var b = pre.filter(item => !bMap[item])
console.log(b)

=> [1,2]

生成哈希表,哈希表的寻址是直接性的,不需要for循环遍历,includes需要每次遍历成哈希表以后节省了遍历,所以速度比较快

arr.reduce(function(prev,cur,index,arr){

}, init);
有四个参数prev 表示上一次调用回调时的返回值,或者初始值 init;cur 表示当前正在处理的数组元素;index 表示当前正在处理的数组元素的索引,若提供 init 值,则索引为0,否则索引为1;init 表示初始值。通常情况会用到前两个参数。

那么在秀刀操作中,使用了前两个参数,初始值为一个空对象,其实就会将数组变成的值变成一个键值对的形式,1就是给对象的属性复制,这里也可以写成true比较好理解,最后在通过对象的方式去寻找。

如果是一个对象数组呢,我们就需要绑定对象中唯一值:
比如:

1
2
3
4
5
var bMap = arr1.reduce((map, i) => {
map[i.userId] = true;
return map;
}, {});
var result = arr2.filter(item => !bMap[item.userId]);

如果有两个对象数组,分别数组a与b中的差异,就可以将上边的代码封装为一个方法:

1
2
3
4
5
6
7
8
splitCaptainList(arr1, arr2) {
var bMap = arr1.reduce((map, i) => {
map[i.userId] = true;
return map;
}, {});
var result = arr2.filter(item => !bMap[item.userId]);
return result
}

如果你有什么更好的方法或者文章有不正确的内容,很开心能跟你交流,QQ:39004003 [笑脸]