数组去重不管是面试还是平常业务都会经常遇到,一般同学见状都会嘴角微微上扬,反手就是一个嵌套循环,嘿嘿~深藏功与名….
还有没有其它去重方式呢?今天来总结一下有哪些花里胡哨的去重方法!!!
1、Set
原理:Set类似于数组,但是成员的值都是唯一的,接受一个数组或类数组作为参数
let arr1 = [1, 1, 2, "true", true, true, undefined, undefined, null, null, NaN, NaN, {}, {}, {a:1}, {a:1}]
let result1 = Array.from(new Set(arr1))
console.log(result1) // (11) [1, 2, "true", true, undefined, null, NaN, {}, {}, {a:1}, {a:1}]
复制代码
2、indexOf() + 循环
原理:创建一个空数组来判断是否存在,不存在则push到新数组中
let arr2 = [1, 1, 2, "true", true, true, undefined, undefined, null, null, NaN, NaN, {}, {}, {a:1}, {a:1}]
let result2 = [];
for (let i = 0; i < arr2.length; i++) {
if (result2.indexOf(arr2[i]) === -1) { // indexOf() === -1表示没找到
result2.push(arr2[i])
}
}
console.log(result2) // (12) [1, 2, "true", true, undefined, null, NaN, NaN, {}, {}, {a:1}, {a:1}]
复制代码
3、splice() + 嵌套循环
原理:splice()方法可以实现删除,并且改变原数组,然后通过双重循环对比实现删除
let arr3 = [1, 1, 2, "true", true, true, undefined, undefined, null, null, NaN, NaN, {}, {}, {a:1}, {a:1}]
for (let i = 0; i < arr3.length; i++) {
for (let j = i + 1; j < arr3.length; j++) {
if (arr3[i] === arr3[j]) {
arr3.splice(j, 1) //splice() 第一个参数表示从哪个元素开始,第二个表示要删除元素个数
}
}
}
console.log(arr3) // (12) [1, 2, "true", true, undefined, null, NaN, NaN, {}, {}, {a:1}, {a:1}]
复制代码
4、sort()+前后元素对比
原理:先用sort()方法把数组排序,这样相同的元素就在一起了,然后通过前后对比,如果不一样则push到新数组中
let arr4 = [1, 1, 2, "true", true, true, undefined, undefined, null, null, NaN, NaN, {}, {}, {a:1}, {a:1}]
arr4 = arr4.sort();
let result4 = [arr4[0]]
for (let i = 1; i < arr4.length; i++) {
if (arr4[i] !== arr4[i-1]) { // 后一个与前面对比
result4.push(arr4[i])
}
}
console.log(result4) // (12) [1, 2, NaN, NaN, {}, {}, {a:1}, {a:1}, null, "true", true, undefined]
复制代码
5、对象属性判断
原理:利用对象属性不能相同去重,我们可构造一个空对象,让后把数组元素变为对象属性,判断是否属性存在,如果不存在则push到新数组中。缺点是对象属性会隐式转换为字符串,如true和‘true’会判断为相同
let arr5 = [1, 1, 2, "true", true, true, undefined, undefined, null, null, NaN, NaN, {}, {}, {a:1}, {a:1}]
let result5 = [], obj5 = {};
for (let i = 0; i < arr5.length; i++) {
if (!obj5[arr5[i]]) {
result5.push(arr5[i])
obj5[arr5[i]] = 1;
}
}
console.log(result5) // (7) [1, 2, "true", undefined, null, NaN, {}]
复制代码
6、includes() + 循环
原理:类似于indexOf()方法,只是此方法返回布尔值,判断如果不在则push到新数组中
let arr6 = [1, 1, 2, "true", true, true, undefined, undefined, null, null, NaN, NaN, {}, {}, {a:1}, {a:1}]
let result6 = [];
for (let i = 0; i < arr6.length; i++) {
if (!result6.includes(arr6[i])) { // 如果不存在
result6.push(arr6[i])
}
}
console.log(result6) // (11) [1, 2, "true", true, undefined, null, NaN, {}, {}, {a:1}, {a:1}]
复制代码
7、filter + indexOf()
原理:利用indexOf()方法判断元素索引位置是否相同,如果不相同则说明已存在,则过滤掉
let arr7 = [1, 1, 2, "true", true, true, undefined, undefined, null, null, NaN, NaN, {}, {}, {a:1}, {a:1}]
let result7 = arr7.filter((item, index, arr7) => {
return arr7.indexOf(item) === index // 判断每个值得索引位置
})
console.log(result7) // (10) [1, 2, "true", true, undefined, null, {}, {}, {a:1}, {a:1}]
复制代码
8、Map 键值对集合
原理:类似于对象的键值对集合,利用键不能重复的特点,优点是键可以是如何数据类型,可以说是对象的优化
let arr8 = [1, 1, 2, "true", true, true, undefined, undefined, null, null, NaN, NaN, {}, {}, {a:1}, {a:1}]
let result8 = [], map = new Map();
for (let i = 0; i < arr8.length; i++) {
if (!map.has(arr8[i])) {
result8.push(arr8[i])
map.set(arr8[i], 1)
}
}
console.log(result8) // (11) [1, 2, "true", true, undefined, null, NaN, {}, {}, {a:1}, {a:1}]
复制代码
总结:
其实上面的方法基本上都是利用循环,只是判断元素的方法略有区别。注意的是,基本上所有的方法比较值都是通过===来判断的,但是NaN是个特列,NaN===NaN返回的也是true,所以去重数据最好是不要有NaN。也有一些方法可以比较NaN,比如Set、Map、includes()等
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END