JavaScript数组去重的多种实现方式

前言

在前端开发中,数组去重是一个常见的需求。无论是处理用户数据、API响应还是进行数据清洗,我们都需要掌握去重方法。本文将详细介绍JavaScript中数组去重的多种实现方式。

1. 使用Set数据结构(ES6推荐)

javascript

ini 复制代码
const arr = [1, 2, 2, 3, 4, 4, 5, 'a', 'a'];
const uniqueArr = [...new Set(arr)];
console.log(uniqueArr); // [1, 2, 3, 4, 5, "a"]

Set 是 ES6 引入的一种新的数据结构,它类似于数组,但是成员的值都是唯一的,没有重复的值。

javascript

scss 复制代码
// Set的基本使用
const arr1 = new Set()
arr1.add(1)
arr1.add(2)
arr1.add(3)
arr1.add(1)  // 重复添加
console.log(arr1)  // {1, 2, 3} - 重复的自动过滤

2. 使用filter + indexOf方法

javascript

ini 复制代码
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]

这里利用了filter方法和indexOf方法的特性:

  • filter会遍历数组,将符合条件的元素组成新数组返回
  • indexOf返回元素在数组中第一次出现的位置索引
  • 只有当元素第一次出现时的索引与当前索引相等时,才保留该元素

3. 使用reduce方法

javascript

ini 复制代码
const arr = [1, 2, 2, 3, 4, 4, 5];
const uniqueArr = arr.reduce((acc, current) => {
  return acc.includes(current) ? acc : [...acc, current];
}, []);
console.log(uniqueArr); // [1, 2, 3, 4, 5]

reduce方法通过累积器遍历数组,检查当前元素是否已存在于累积器中,不存在则添加。

4. 使用forEach + includes方法

javascript

ini 复制代码
const arr = [1, 2, 2, 3, 4, 4, 5];
const uniqueArr = [];
arr.forEach(item => {
  if (!uniqueArr.includes(item)) {
    uniqueArr.push(item);
  }
});
console.log(uniqueArr); // [1, 2, 3, 4, 5]

这种方法思路直观:

  • 创建空数组存储结果
  • 遍历原数组,检查元素是否已存在
  • 不存在则添加到结果数组

方法对比

  • forEach:遍历数组执行操作,不关心返回值
  • map:将数组转换为新数组(1:1映射)
  • filter:根据条件筛选数组元素

5. 对象数组去重(基于特定属性)

实际开发中,我们经常需要根据对象属性去重:

javascript

ini 复制代码
const users = [
  {id: 1, name: 'Alice'},
  {id: 2, name: 'Bob'},
  {id: 1, name: 'Alice'},  // 重复
  {id: 3, name: 'Charlie'}
];

// 方法1:使用Map(推荐)
const uniqueUsers = [...new Map(users.map(item => [item.id, item])).values()];

// 方法2:使用reduce
const uniqueUsers2 = users.reduce((acc, current) => {
  const exists = acc.find(item => item.id === current.id);
  return exists ? acc : [...acc, current];
}, []);

console.log(uniqueUsers); // 基于id去重后的数组

Map方法利用键的唯一性,将对象ID作为键,对象本身作为值,最后通过values()获取去重后的对象。

6. 复杂数据类型去重

对于包含对象、数组等复杂数据类型的数组:

javascript

ini 复制代码
const complexArr = [{a:1}, {a:1}, [1,2], [1,2], 'hello', 'hello'];

const uniqueComplex = complexArr.reduce((acc, current) => {
  const isDuplicate = acc.some(item =>
    JSON.stringify(item) === JSON.stringify(current)
  );
  return isDuplicate ? acc : [...acc, current];
}, []);

console.log(uniqueComplex); // 每个元素都是唯一的

这种方法通过JSON.stringify将对象转为字符串进行比较,但要注意对象属性顺序必须一致。

7. 排序后去重(适用于可排序数据)

javascript

ini 复制代码
const arr = [1, 2, 2, 3, 4, 4, 5];
const uniqueArr = arr
  .sort((a, b) => a - b)
  .filter((item, index, array) =>
    index === 0 || item !== array[index - 1]
  );
console.log(uniqueArr); // [1, 2, 3, 4, 5]

先排序,然后过滤掉与前一元素相同的元素。注意这会改变原数组的顺序。

性能对比与使用建议

方法 适用场景
Set 简单数据类型,现代浏览器
filter+indexOf 兼容性要求高
reduce 需要自定义逻辑
Map对象 对象数组去重

日常开发建议

  • 简单数组去重:优先使用 [...new Set(arr)]
  • 对象数组去重:使用 Map 方法
  • 兼容性要求:使用 filter + indexOf
  • 复杂数据:使用 reduce + JSON.stringify
相关推荐
军军君011 小时前
Three.js基础功能学习十三:太阳系实例上
前端·javascript·vue.js·学习·3d·前端框架·three
xiaoqi9222 小时前
React Native鸿蒙跨平台如何实现分类页面组件通过searchQuery状态变量管理搜索输入,实现了分类的实时过滤功能
javascript·react native·react.js·ecmascript·harmonyos
qq_177767372 小时前
React Native鸿蒙跨平台实现应用介绍页,实现了应用信息卡片展示、特色功能网格布局、权限/联系信息陈列、评分展示、模态框详情交互等通用场景
javascript·react native·react.js·ecmascript·交互·harmonyos
2603_949462102 小时前
Flutter for OpenHarmony社团管理App实战:预算管理实现
android·javascript·flutter
wuhen_n2 小时前
JavaScript内存管理与执行上下文
前端·javascript
Hi_kenyon3 小时前
理解vue中的ref
前端·javascript·vue.js
jin1233224 小时前
基于React Native鸿蒙跨平台地址管理是许多电商、外卖、物流等应用的重要功能模块,实现了地址的添加、编辑、删除和设置默认等功能
javascript·react native·react.js·ecmascript·harmonyos
2501_920931704 小时前
React Native鸿蒙跨平台医疗健康类的血压记录,包括收缩压、舒张压、心率、日期、时间、备注和状态
javascript·react native·react.js·ecmascript·harmonyos
橙露5 小时前
React Hooks 深度解析:从基础使用到自定义 Hooks 的封装技巧
javascript·react.js·ecmascript
2501_920931705 小时前
React Native鸿蒙跨平台使用useState管理健康记录和过滤状态,支持多种健康数据类型(血压、体重等)并实现按类型过滤功能
javascript·react native·react.js·ecmascript·harmonyos