数组去重N种方式

  数组去重不管是面试还是平常业务都会经常遇到,一般同学见状都会嘴角微微上扬,反手就是一个嵌套循环,嘿嘿~深藏功与名….

还有没有其它去重方式呢?今天来总结一下有哪些花里胡哨的去重方法!!!

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()等


本文是笔者总结编撰,如有偏颇,欢迎留言指正,若您觉得本文对你有用,不妨点个赞~
关于作者:
GitHub
简书
掘金

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享