1. 使用 Set
Set
是 ES6 引入的数据结构,类似于数组,但 Set
会自动移除重复的值。因此,利用 Set
来去重是最简单和最快速的方法。
const array = [1, 2, 2, 3, 4, 4, 5];
const uniqueArray = [...new Set(array)];
console.log(uniqueArray); // [1, 2, 3, 4, 5]
优点:
- 简洁明了,代码量少。
- 性能较好,时间复杂度为 O(n)。
缺点:
Set
只能去除原始类型(如number
、string
、boolean
)的重复,对于复杂对象(如数组、对象)的重复判断需要额外处理。
2. 使用 filter
和 indexOf
通过 filter
遍历数组,然后使用 indexOf
来判断当前元素的索引是否是第一次出现,确保只保留第一次出现的元素。
const array = [1, 2, 2, 3, 4, 4, 5];
const uniqueArray = array.filter((item, index) => array.indexOf(item) === index);
console.log(uniqueArray); // [1, 2, 3, 4, 5]
优点:
- 简单易懂,适合初学者使用。
缺点:
indexOf
每次都要遍历数组,所以时间复杂度较高,为 O(n²),不适合大数据量场景。
3. 使用 reduce
reduce
是数组的高阶方法,可以用来累积处理数组,借助 reduce
来实现去重。
const array = [1, 2, 2, 3, 4, 4, 5];
const uniqueArray = array.reduce((acc, item) => {
if (!acc.includes(item)) {
acc.push(item);
}
return acc;
}, []);
console.log(uniqueArray); // [1, 2, 3, 4, 5]
优点:
- 使用
reduce
可以直接在一次遍历中实现去重,适合对数组做进一步的操作。
缺点:
includes
方法也会遍历数组,时间复杂度为 O(n²),在处理大数组时效率不高。
4. 使用 Map
或 Object
作为哈希表
通过 Map
或 Object
来记录元素是否已经出现过,可以大大提高查找的效率。
const array = [1, 2, 2, 3, 4, 4, 5];
const uniqueArray = [];
const seen = new Map();
array.forEach(item => {
if (!seen.has(item)) {
seen.set(item, true);
uniqueArray.push(item);
}
});
console.log(uniqueArray); // [1, 2, 3, 4, 5]
优点:
- 利用哈希表的特性,查找速度快,时间复杂度为 O(n)。
- 比
filter
+indexOf
或reduce
更高效。
缺点:
- 代码较长,稍微复杂一些。
- 使用
Map
或Object
来处理复杂对象去重时更适合。
5. 手动双重循环
可以使用双重循环手动去重,外层循环遍历数组,内层循环检查当前元素是否已经在结果数组中出现过。
const array = [1, 2, 2, 3, 4, 4, 5];
const uniqueArray = [];
for (let i = 0; i < array.length; i++) {
let exists = false;
for (let j = 0; j < uniqueArray.length; j++) {
if (array[i] === uniqueArray[j]) {
exists = true;
break;
}
}
if (!exists) {
uniqueArray.push(array[i]);
}
}
console.log(uniqueArray); // [1, 2, 3, 4, 5]
优点:
- 不依赖其他内置方法,纯手动实现。
缺点:
- 性能最差,时间复杂度为 O(n²),不推荐在实际项目中使用。
6. 处理复杂对象去重(深度比较)
如果数组中包含对象类型,需要通过自定义比较逻辑去重。例如使用对象的某个属性来判断重复性:
const array = [{id: 1}, {id: 2}, {id: 2}, {id: 3}];
const uniqueArray = array.filter((item, index, self) =>
index === self.findIndex((obj) => obj.id === item.id)
);
console.log(uniqueArray); // [{id: 1}, {id: 2}, {id: 3}]
优点:
- 适用于复杂对象的去重。
缺点:
- 复杂度较高,需要根据具体场景进行优化。
总结
方法 | 时间复杂度 | 适用场景 | 优点 | 缺点 |
---|---|---|---|---|
Set | O(n) | 原始类型去重 | 简单高效,适合简单数据类型去重 | 不适合对象、复杂数据类型 |
filter + indexOf | O(n²) | 小型数据集,简单去重 | 代码易懂 | 性能较差,不适合大数据 |
reduce | O(n²) | 数据处理过程中去重 | 可以与其他操作结合 | 性能较差 |
Map 或 Object | O(n) | 原始类型去重、效率高 | 高效,适合需要大量查找的场景 | 代码稍显复杂 |
手动双重循环 | O(n²) | 教学、展示用 | 不依赖其他方法 | 性能最差,代码冗长 |
复杂对象去重 | O(n²) | 对象数组去重 | 可以自定义去重规则 | 需要定制化实现,性能较低 |
根据数组数据的类型和具体需求,选择最合适的去重方案。对于简单数据类型,使用 Set
是最方便的;对于对象类型数组,则需要通过自定义逻辑实现。