【JavaScript】数组去重

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 只能去除原始类型(如 numberstringboolean)的重复,对于复杂对象(如数组、对象)的重复判断需要额外处理。

2. 使用 filterindexOf

通过 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. 使用 MapObject 作为哈希表

通过 MapObject 来记录元素是否已经出现过,可以大大提高查找的效率。

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 + indexOfreduce 更高效。
缺点:
  • 代码较长,稍微复杂一些。
  • 使用 MapObject 来处理复杂对象去重时更适合。

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}]
优点:
  • 适用于复杂对象的去重。
缺点:
  • 复杂度较高,需要根据具体场景进行优化。

总结

方法时间复杂度适用场景优点缺点
SetO(n)原始类型去重简单高效,适合简单数据类型去重不适合对象、复杂数据类型
filter + indexOfO(n²)小型数据集,简单去重代码易懂性能较差,不适合大数据
reduceO(n²)数据处理过程中去重可以与其他操作结合性能较差
MapObjectO(n)原始类型去重、效率高高效,适合需要大量查找的场景代码稍显复杂
手动双重循环O(n²)教学、展示用不依赖其他方法性能最差,代码冗长
复杂对象去重O(n²)对象数组去重可以自定义去重规则需要定制化实现,性能较低

根据数组数据的类型和具体需求,选择最合适的去重方案。对于简单数据类型,使用 Set 是最方便的;对于对象类型数组,则需要通过自定义逻辑实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秀秀_heo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值