今天看到一道面试题是用数组的filter、reduce方法来做去重,很有意思的题目。先来看一下filter方法,filter过滤简单说就是返回一个满足条件的对象集合,刚开始我在想怎么设置这个过滤条件呢?我们先看filter回调函数中的参数
filter(callback(element[, index[, array]])[, thisArg])
element当前处理元素,index索引,array原数组,thisArg执行callback的this值
先看一下代码的实现,在说为什么
function distinctByFilter(arr) {
return arr.filter((item, index) => arr.indexOf(item) === index);
}
let arr = [1, 2, 2, 3, 4, 5, 5, 5];
console.log(distinctByFilter(arr)); // [1,2,3,4,5]
这个方法利用了数组的indexOf方法只会返回第一个索引,当有两个2的时候只返回第一个2的索引,所以我们利用索引不同来判断是否可以过滤掉这个元素。 同样的我们也可以通过例如 forEach、Map等只要可以遍历当前对象和索引都可以用这种思路来做去重。
来看reduce怎么做去重,这个我平时几乎没太用过,所以一下没有太好的思路,我就在mdn上仔细看了他用例,直到看到这段代码才豁然开朗,不了解reduce参数的请点击此处。
var names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];
var countedNames = names.reduce(function (allNames, name) {
if (name in allNames) {
allNames[name]++;
}
else {
allNames[name] = 1;
}
return allNames;
}, {});
// countedNames is:
// { 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 }
惯例还是先上一下实现的代码
function distinctByReduce(arr) {
return arr.reduce((acc, cur) => {
acc.includes(cur) || acc.push(cur);
return acc;
}, []);
}
let arr = [1, 2, 2, 3, 4, 5, 5, 5];
console.log(distinctByReduce(arr));
我们利用的是reduce的最后一个参数initialValue,那我们的acc累计器在初始的时候就是一个空数组,cur是当前元素,我们只需判断累计中是否包含有当前元素即可,最后返回的就是我们去除重复值之后的新数组。
function distinctByReduce(arr) {
return [...new Set(arr)];
}
let arr = [1, 2, 2, 3, 4, 5, 5, 5];
console.log(distinctByReduce(arr));