数组去重是JavaScript开发中非常常见的需求,常用于数据处理、集合操作等场景。为了满足不同性能要求和开发场景,JavaScript提供了多种实现数组去重的方法。下面详细介绍八种常见的数组去重方式,包括从基础到高级的实现方式。
1. 双重循环法
这是最基础的去重方法,使用两层循环来检查数组中的每个元素是否已存在于结果数组中。
Array.prototype.unique = function () {
const newArray = [];
let isRepeat;
for (let i = 0; i < this.length; i++) {
isRepeat = false;
for (let j = 0; j < newArray.length; j++) {
if (this[i] === newArray[j]) {
isRepeat = true;
break;
}
}
if (!isRepeat) {
newArray.push(this[i]);
}
}
return newArray;
}
- 优点:简单易懂,适合小型数组。
- 缺点:时间复杂度为 O(n²),性能较低,尤其在数组较大时不推荐使用。
2. 使用 indexOf()
方法
通过 indexOf()
方法检查新数组中是否存在该元素,从而实现去重。
Array.prototype.unique = function () {
const newArray = [];
this.forEach(item => {
if (newArray.indexOf(item) === -1) {
newArray.push(item);
}
});
return newArray;
}
- 优点:比双重循环性能稍优。
- 缺点:
indexOf()
本身是 O(n) 操作,整体性能依旧不高。
3. 通过 sort()
方法排序后去重
将数组进行排序,然后去掉相邻重复的元素。
Array.prototype.unique = function () {
const newArray = [];
this.sort();
for (let i = 0; i < this.length; i++) {
if (this[i] !== this[i + 1]) {
newArray.push(this[i]);
}
}
return newArray;
}
- 优点:借助排序简化去重逻辑。
- 缺点:需要排序,且可能改变数组元素的顺序,适用于不关注顺序的场景。
4. 使用 includes()
方法
通过 includes()
方法判断数组中是否存在该元素,若不存在则加入新数组。
Array.prototype.unique = function () {
const newArray = [];
this.forEach(item => {
if (!newArray.includes(item)) {
newArray.push(item);
}
});
return newArray;
}
- 优点:代码简洁易读。
- 缺点:和
indexOf()
一样,includes()
也是 O(n) 操作,性能较低。
5. 使用 reduce()
方法
通过 reduce()
方法遍历数组,构造一个去重后的数组。
Array.prototype.unique = function () {
return this.sort().reduce((init, current) => {
if (init.length === 0 || init[init.length - 1] !== current) {
init.push(current);
}
return init;
}, []);
}
- 优点:巧妙地利用
reduce()
和排序。 - 缺点:同样会改变数组顺序,适合不关心顺序的去重。
6. 通过对象键值对去重
将数组的每个元素作为对象的键,通过键的唯一性来实现去重。
Array.prototype.unique = function () {
const newArray = [];
const tmp = {
};
for (let i = 0; i < this.length; i++) {
if (!tmp[typeof this[i] + this[i]]) {
tmp[typeof this[i] + this[i]] = 1;
newArray.push(this[i]);
}
}
return newArray;
}
- 优点:通过对象的特性进行去重,避免嵌套循环。
- 缺点:不能处理复杂数据类型,性能受限于对象的键值操作。
7. 使用 Map
(最优解)
通过 Map
对象来存储数组元素,利用 Map
的键唯一性来进行去重。
Array.prototype.unique = function () {
const tmp = new Map();
return this.filter(item => {
return !tmp.has(item) && tmp.set(item, 1);
})
}
- 优点:效率高,
Map
的键检索速度快。 - 缺点:代码稍复杂,但性能非常出色。
8. 使用 Set
(最简便)
Set
是 ES6 提供的集合类型,它的成员是唯一的,因此可以非常方便地实现去重。
Array.prototype.unique = function () {
return [...new Set(this)];
}
- 优点:最简洁高效的去重方式,性能最好。
- 缺点:适用于现代浏览器或支持 ES6 的环境。
性能对比
在实际项目中,Set
和 Map
是目前最优的去重方案,具有很高的性能,尤其适合处理大数组。Set
实现最为简洁,性能优异,因此在现代 JavaScript 开发中推荐使用。
然而,如果需要兼容老旧浏览器或者环境不支持 Set
、Map
,可以选择 indexOf()
或 includes()
的实现方式,但这些方法的性能相对较低,不适合处理过大的数据集。
结语
本文介绍了八种数组去重的方法,涵盖了从基础到高级的实现方式。通过对比,可以看出使用 Set
和 Map
是最为高效的方案,尤其适用于处理大量数据。在实际开发中,开发者可以根据具体场景选择最适合的去重方式,以达到性能和代码简洁性的平衡。