前言
数组去重已经成为面试过程中很常见的笔试题目了,在过去的2023年十次面试笔试题当中,都占了九成那么多,这时候我们更要掌握并且懂的灵活运用,先从简单后突破原理再展开讲个普通的例子,再结合业务展开说。感兴趣的朋友们可以接着往下看。
数组去重
为何数组去重?
给你一串数据,数组里面包含重复的数组和非数字,对数组去重,将重复的元素去掉,从而得到一串唯一的数组。数组形式如下所示。
const arr = [
1,
2,
2,
"abc",
"abc",
true,
true,
false,
false,
undefined,
undefined,
NaN,
NaN
];
实现方法
关于数组去重实现方法有很多,这里将介绍三种方法。
方法一:Set
先来说一种最简单直接的 API方法,代码如下所示:
const result = Array.from(new Set(arr));
console.log(result);
// [ 1, 2, 'abc', true, false, undefined, NaN ]
Set中的元素都是不重复的,Set对象仅能存储不同的值,因此达到去重的效果。
方法二:forEach() 结合 includes()
forEach方法用来遍历数组,includes方法用来检测数组是否有某个值。实现代码如下。
function removeNumber(arr) {
const newarr = [];
arr.forEach((element) => {
if (!newarr.includes(element)) {
newarr.push(element);
}
});
return newarr;
}
以上两个方法结合arr使用!
方法三:对象属性名不能重复
利用对象的属性不能相同的特点进行去重,也是可以考虑的一种方法。代码如下所示。
let arr = [12, 1, 12, 3, 1, 88, 66, 9, 66];
function unique(ary) {
let obj = {};
for (let i = 0; i < ary.length; i++) {
let cur = ary[i];
if (obj[cur]需 {
//ary.splice(i,1);// 导致数组塌陷
ary[i] = ary[ary.length - 1];
ary.length--;// 删除最后一项
i--;
continue;
}
obj[cur] = cur;// 给obj新增键值对;属性名和属性值是一样的
}
}
unique(arr);
方法四:indexOf
indexof方法用于在数组中查找指定元素第一次出现的位置。
let arr = [12, 1, 12, 3, 1, 88, 66, 9, 66];
function unique(ary) {
let newAry = [];
for (let i = 0; i < ary.length; i++) {
let cur = ary[i];
if (newAry.indexOf(cur) === -1) {
newAry.push(cur);
}
}
return newAry;
}
unique(arr)
方法五:includes :包含;如果数组包含那一项,返回true;不包含返回false;
let arr = [12, 1, 12, 3, 1, 88, 66, 9, 66];
function unique(ary) {
let newAry = [];
let len = ary.length;
for (let i = 0; i < len; i++) {
let cur = ary[i];
if (!newAry.includes(cur)) {
newAry.push(cur);
}
}
return newAry;
}
console.log(unique(arr));
方法六:hasOwnProperty : 检测属性名是否是对象的一个私有属性;返回一个布尔值;
这就是我在其中一次面试中对数组去重的一次总结,也算是我对数组去重的巩固。我们总共介绍了三种方式,分别是Set方法、forEach()结合includes()、利用对象的属性,这三种方法各有各的特点,都能达到去重的效果。
let arr = [12, 1, 12, 3, 1, 88, 66, 9, 66];
function unique(ary) {
let obj = {};
return ary.filter(function (item, index, a) {
// item : 数组每一个成员
// index: 成员对应的索引
// a : 整个数组
// hasOwnProperty来校验的该属性是否出现过;
return obj.hasOwnProperty(typeof item + item) ? false : obj[typeof item + item] = true;
if (obj.hasOwnProperty(typeof item + item)) {
return false
} else {
obj[typeof item + item] = true;
return true;
}
})
}
console.log(unique(arr))
方法七:filter+indexOf
let arr = [12, 1, 12, 3, 1, 88, 66, 9, 66];
function unique(ary) {
return ary.filter(function (item, index, a) {
return ary.indexOf(item) === index;
})
}
console.log(unique(arr));
方法八:splice
let arr = [12, 1, 12, 3, 1, 88, 66, 9, 66];
function unique(ary) {
for (let i = 0; i < ary.length; i++) {
for (j = i + 1; j < ary.length; j++) {
if (ary[i] === ary[j]) {
ary.splice(j, 1);
j--;
}
}
}
return ary;
}
unique(arr);
方法九:递归
let arr = [12, 1, 12, 3, 1, 88, 66, 9, 66];
function unique(ary) {
let len = ary.length;
ary = ary.sort(function (a, b) {
return a - b;
});
function loop(index) {
if (index >= 1) {
if (ary[index] === ary[index - 1]) {
ary.splice(index, 1);
}
loop(index - 1)
}
}
loop(len - 1);
return ary;
}
console.log(unique(arr));
方法十:Map :利用了Map数据结构存值的特点;
let arr = [12, 1, 12, 3, 1, 88, 66, 9, 66];
function unique(ary) {
let newAry = [];
let map = new Map();
for (let i = 0; i < ary.length; i++) {
if (!map.has(ary[i])) {
map.set(ary[i], true);
newAry.push(ary[i]);
}
}
}
unique(arr);
方法十一:reduce
let arr = [12, 1, 12, 3, 1, 88, 66, 9, 66];
function unique(ary) {
// reduce : 第一个是函数,第二个参数会传给第一次回调的prev;
return ary.reduce((prev, next) => {
// 该函数返回值是下一次执行的prev;
return prev.includes(next) ? prev : [...prev, next];
}, [])
}
console.log(unique(arr));
方法十二:类似于方法一的set,用了剩余运算符...
let arr = [12, 1, 12, 3, 1, 88, 66, 9, 66];
let a = [...new Set(arr)];
console.log(a);
方法十三:sort
利用sort排序方法,对a减b形式再利用for循环进行查找,查找到了向重的数字使用splice割掉
let arr = [12, 1, 12, 3, 1, 88, 66, 9, 66];
function unique(ary) {
let a = ary.sort(function (a, b) {
return a - b;
});
for (let i = 0; i < a.length; i++) {
if (a[i] === a[i + 1]) {
a.splice(i + 1, 1);
i--;
}
}
return a;
}
unique(arr)