JavaScript中的数组去重方法详解
字数 986 2025-11-11 18:55:48

JavaScript中的数组去重方法详解

数组去重是JavaScript中常见的需求,涉及多种实现方法和性能考量。下面将从基础到高级逐步讲解不同的去重方式及其原理。

1. 使用Set(ES6最简单的方法)

原理:Set是ES6引入的数据结构,其元素唯一性可自动过滤重复值。
步骤

  1. 将数组转换为Set,重复值会被自动去除。
  2. 将Set转回数组。
    代码示例
const arr = [1, 2, 2, 3, 4, 4, 5];
const uniqueArr = [...new Set(arr)]; // 或 Array.from(new Set(arr))
console.log(uniqueArr); // [1, 2, 3, 4, 5]

优点:代码简洁,效率高(时间复杂度O(n))。
缺点:无法处理特殊场景(如对象元素去重)。


2. 使用filter与indexOf

原理:利用indexOf返回首次出现索引的特性,筛选出第一次出现的元素。
步骤

  1. 遍历数组,检查当前元素的索引是否等于indexOf返回的索引。
  2. 若相等则保留,否则过滤。
    代码示例
const arr = [1, 2, 2, 3, 4, 4, 5];
const uniqueArr = arr.filter((item, index) => arr.indexOf(item) === index);
console.log(uniqueArr); // [1, 2, 3, 4, 5]

优点:兼容性好(ES5)。
缺点:时间复杂度O(n²),大数据量时性能较差。


3. 使用reduce

原理:通过累加器逐步构建不含重复值的数组。
步骤

  1. 初始化空数组作为累加器。
  2. 遍历原数组,若当前元素不在累加器中则追加。
    代码示例
const arr = [1, 2, 2, 3, 4, 4, 5];
const uniqueArr = arr.reduce((acc, cur) => acc.includes(cur) ? acc : [...acc, cur], []);
// 或使用push提升性能:  
// const uniqueArr = arr.reduce((acc, cur) => {
//   if (!acc.includes(cur)) acc.push(cur);
//   return acc;
// }, []);

优点:逻辑清晰,可灵活扩展。
缺点:包含检查(includes)会导致O(n²)复杂度。


4. 使用Map(处理对象去重)

原理:利用Map的键唯一性,以特定规则(如序列化)作为键去重。
步骤

  1. 创建Map,遍历数组并以元素特征(如JSON.stringify)为键存储。
  2. 提取Map的值作为结果。
    代码示例(对象去重):
const arr = [{id: 1}, {id: 2}, {id: 1}];
const map = new Map();
arr.forEach(item => map.set(item.id, item)); // 以id为键去重
const uniqueArr = Array.from(map.values());
console.log(uniqueArr); // [{id: 1}, {id: 2}]

优点:可自定义去重规则,适合复杂数据类型。
缺点:需明确去重依据(如属性名)。


5. 性能优化:一次遍历+对象缓存

原理:通过对象属性查询(O(1))替代数组查询(O(n)),提升效率。
步骤

  1. 创建空对象和结果数组。
  2. 遍历数组,若元素未在对象中出现则标记并存入结果数组。
    代码示例
const arr = [1, 2, 2, 3, 4, 4, 5];
const uniqueArr = [];
const cache = {};
arr.forEach(item => {
  if (!cache[item]) {
    cache[item] = true;
    uniqueArr.push(item);
  }
});

优点:时间复杂度O(n),性能最优。
缺点:仅适用于基本类型(对象需转为字符串键)。


总结与选择建议

  • 简单场景:优先使用Set(代码简洁,效率高)。
  • 兼容性要求:使用filter+indexOf(ES5)。
  • 复杂数据类型:结合Map或自定义哈希规则。
  • 极致性能:一次遍历+对象缓存(避免嵌套循环)。

通过理解不同方法的原理与适用场景,可灵活应对实际开发中的去重需求。

JavaScript中的数组去重方法详解 数组去重是JavaScript中常见的需求,涉及多种实现方法和性能考量。下面将从基础到高级逐步讲解不同的去重方式及其原理。 1. 使用Set(ES6最简单的方法) 原理 :Set是ES6引入的数据结构,其元素唯一性可自动过滤重复值。 步骤 : 将数组转换为Set,重复值会被自动去除。 将Set转回数组。 代码示例 : 优点 :代码简洁,效率高(时间复杂度O(n))。 缺点 :无法处理特殊场景(如对象元素去重)。 2. 使用filter与indexOf 原理 :利用 indexOf 返回首次出现索引的特性,筛选出第一次出现的元素。 步骤 : 遍历数组,检查当前元素的索引是否等于 indexOf 返回的索引。 若相等则保留,否则过滤。 代码示例 : 优点 :兼容性好(ES5)。 缺点 :时间复杂度O(n²),大数据量时性能较差。 3. 使用reduce 原理 :通过累加器逐步构建不含重复值的数组。 步骤 : 初始化空数组作为累加器。 遍历原数组,若当前元素不在累加器中则追加。 代码示例 : 优点 :逻辑清晰,可灵活扩展。 缺点 :包含检查( includes )会导致O(n²)复杂度。 4. 使用Map(处理对象去重) 原理 :利用Map的键唯一性,以特定规则(如序列化)作为键去重。 步骤 : 创建Map,遍历数组并以元素特征(如JSON.stringify)为键存储。 提取Map的值作为结果。 代码示例 (对象去重): 优点 :可自定义去重规则,适合复杂数据类型。 缺点 :需明确去重依据(如属性名)。 5. 性能优化:一次遍历+对象缓存 原理 :通过对象属性查询(O(1))替代数组查询(O(n)),提升效率。 步骤 : 创建空对象和结果数组。 遍历数组,若元素未在对象中出现则标记并存入结果数组。 代码示例 : 优点 :时间复杂度O(n),性能最优。 缺点 :仅适用于基本类型(对象需转为字符串键)。 总结与选择建议 简单场景 :优先使用 Set (代码简洁,效率高)。 兼容性要求 :使用 filter + indexOf (ES5)。 复杂数据类型 :结合 Map 或自定义哈希规则。 极致性能 :一次遍历+对象缓存(避免嵌套循环)。 通过理解不同方法的原理与适用场景,可灵活应对实际开发中的去重需求。