几乎每个面试官都要问的数组去重的方法
有一位面试官有提醒我,数组内可能还会嵌套数组或者对象,数组内的元素类型可能也不尽相同,希望大家在实际操作中可以考虑到这些情况。
var arr = ['1','2',3, 2, 2, 4, 4, 4];
1 最简单的方法: Set
Array.prototype.distinct = function(){
return [...new Set(this)];
}
MDN:
Set 对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用。
语法:new Set([iterable]);
注意它返回的是一个Set对象,所以在处理数组的时候用…拆分再组装成一个新数组对象。
Set 的计算法则和 === 是不同的
- +0 和 -0 是不同的值
- NaN和undefined都可以被存储在Set 中,NaN之间被视为相同的值(尽管 NaN !== NaN)。
iterable
解释一下这里的 iterable:
MDN Reference
for of 语句可以遍历的 iterable 对象包括:String,Array,类Array(arguments或NodeList),TypedArray,Map, Set,还有用户自定义的 iterables。
这里面还包括了generator函数…可以查看reference中的案例
for of语句主要是遍历的对象的值value,相对于for in遍历的是对象的key。
这里不多赘述,可以查看JS数组遍历方法详解。
Set方法和属性
Set.prototype.size:对象的值的个数(Set.length 为 0)
方法:
- Set.add(value): 返回Set对象
- Set.clear() 移除所有元素
- Set.delete(value) : 返回 Set.prototype.has(value)
- Set.prototype.entries():把value变为数组的形式。entries是一个数组,每个元素是Set的key+value组成的数组,为了和map的形式对应,把Set的key设为和Value等值的元素。见下文代码
- Set.prototype.forEach(callbackFn[, thisArg]): 给Set每个元素调用callback函数,this表示context
- Set.prototype.has(value) 返回boolean 表示value是否存在
- Set.prototype.keys() 与values()方法相同
- Set.prototype.values()
// Set.prototype.entries()
const set1 = new Set();
set1.add(42);
set1.add('forty two');
const iterator1 = set1.entries();
for (let entry of iterator1) {
console.log(entry);
// expected output: [42, 42]
// expected output: ["forty two", "forty two"]
}
//求交集
// intersect can be simulated via
var intersection = new Set([...set1].filter(x => set2.has(x)));
//求差集
// difference can be simulated via
var difference = new Set([...set1].filter(x => !set2.has(x)));
2 map对象储存
存放在map对象中。key为type+item,value为item,从而避免同类型的数据难以区分的问题
Array.prototype.distinct = function(){
let arr_map = {};
let result = [];
//遍历数组,储存到map中
arr.forEach(item => {
let key = typeof(item)+'_'+item;
arr_map[key] = item;
});
//map的value保存为数组
Object.keys(arr_map).forEach( item => {
let val = arr_map[item];
result.push(val);
});
return result;
}