❤ 写在前面
如果觉得对你有帮助的话,点个小❤❤ 吧,你的支持是对我最大的鼓励~
个人独立开发wx小程序,感谢支持!
前言:为什么需要数组去重?
想象一下,你正在整理一个装满各种颜色袜子的抽屉。你会发现有很多双相同颜色的袜子,为了节省空间,你会把重复的袜子拿出来。在前端开发中,处理数据时也会遇到类似情况——数组中的重复元素会浪费资源、影响性能,甚至导致数据错误。
今天,我们就来探索前端开发中数组去重的七种方法,每种方法都有其独特的“武器特性”!
方法一:Set大法(ES6推荐)
这是目前最简洁、最高效的方法,就像一把锋利的瑞士军刀!
constarr=[1,2,2,3,4,4,5];constuniqueArr=[...newSet(arr)];console.log(uniqueArr);// [1, 2, 3, 4, 5]原理图:
原始数组 → Set容器(自动去重) → 展开为数组 → 去重后的数组优点:代码简洁,性能优秀
缺点:无法处理特殊对象去重(如:对象、NaN等特殊情况需注意)
方法二:Filter + IndexOf(经典组合)
这种方法像是侦探办案,检查每个元素是否是第一次出现:
functionunique(arr){returnarr.filter((item,index)=>{returnarr.indexOf(item)===index;});}constarr=['苹果','香蕉','苹果','橙子','香蕉'];console.log(unique(arr));// ['苹果', '香蕉', '橙子']流程图:
开始 ↓ 遍历数组每个元素 ↓ 检查当前元素首次出现位置是否等于当前位置 ↓ 是 → 保留元素 ↓ 否 → 过滤掉 ↓ 返回新数组方法三:Reduce累积器
使用reduce像是用漏斗过滤,只保留第一次遇到的元素:
constarr=[1,2,2,3,3,3,4];constuniqueArr=arr.reduce((acc,current)=>{if(!acc.includes(current)){acc.push(current);}returnacc;},[]);console.log(uniqueArr);// [1, 2, 3, 4]方法四:双层循环(最原始的方法)
这是最基础的实现方式,就像手动检查每双袜子:
functionunique(arr){constresult=[];for(leti=0;i<arr.length;i++){letisDuplicate=false;for(letj=0;j<result.length;j++){if(arr[i]===result[j]){isDuplicate=true;break;}}if(!isDuplicate){result.push(arr[i]);}}returnresult;}方法五:Object键值法
利用对象的键名不可重复的特性:
functionunique(arr){constobj={};constresult=[];arr.forEach(item=>{if(!obj[item]){obj[item]=true;result.push(item);}});returnresult;}⚠️注意:这种方法会将数字和字符串视为相同键,如1和'1'会被认为是重复的。
方法六:Map数据结构
Map比Object更适合处理复杂类型的去重:
functionunique(arr){constmap=newMap();constresult=[];arr.forEach(item=>{if(!map.has(item)){map.set(item,true);result.push(item);}});returnresult;}// 可以处理对象引用去重constobj1={name:'张三'};constobj2={name:'张三'};constarr=[obj1,obj2,obj1];console.log(unique(arr).length);// 2(obj1只出现一次,obj2是不同引用)方法七:排序相邻去重法
先排序,然后比较相邻元素:
functionunique(arr){constsortedArr=[...arr].sort();constresult=[sortedArr[0]];for(leti=1;i<sortedArr.length;i++){if(sortedArr[i]!==sortedArr[i-1]){result.push(sortedArr[i]);}}returnresult;}特殊场景处理
1. 对象数组去重
// 根据对象的某个属性去重functionuniqueByKey(arr,key){constmap=newMap();returnarr.filter(item=>{if(!map.has(item[key])){map.set(item[key],true);returntrue;}returnfalse;});}constusers=[{id:1,name:'Alice'},{id:2,name:'Bob'},{id:1,name:'Alice'},// 重复ID];console.log(uniqueByKey(users,'id'));// 前两个对象2. 处理NaN的重复
// Set可以正确处理NaN去重constarr=[NaN,NaN,1,2,1];console.log([...newSet(arr)]);// [NaN, 1, 2]性能对比实验
让我们通过一个简单的性能测试来看看各种方法的效率差异:
// 生成测试数据consttestArray=[];for(leti=0;i<10000;i++){testArray.push(Math.floor(Math.random()*1000));}// 测试函数执行时间functiontestPerformance(fn,arr){conststart=performance.now();fn(arr);constend=performance.now();returnend-start;}// 测试结果通常如下(时间从短到长):// 1. Set方法 √// 2. Object键值法// 3. Map方法// 4. Filter + IndexOf// 5. Reduce方法// 6. 排序相邻法// 7. 双层循环选择合适的方法:决策流程图
开始选择去重方法 ↓ 需要考虑性能吗? → 是 → 使用Set方法(最快) ↓否 数组中有对象吗? → 是 → 使用Map或根据属性去重 ↓否 需要兼容老浏览器吗? → 是 → 使用Filter+indexOf或Object键值法 ↓否 代码简洁更重要吗? → 是 → 使用Set或Reduce ↓否 使用Filter+indexOf(平衡选择)总结与最佳实践
- 现代项目首选:
[...new Set(arr)]- 简洁高效 - 对象数组去重:使用Map或根据特定属性去重
- 兼容性要求:Filter + IndexOf或Object键值法
- 性能敏感场景:Set方法最快,其次是Object键值法
- 代码可读性:Reduce方法语义清晰,适合函数式编程
实战小挑战
试试这个综合题目:
// 有一个混合类型的数组,如何去除所有类型的重复?constmixedArray=[1,'1',1,true,'true',true,null,undefined,null,{a:1},{a:1},// 注意:这两个对象看起来一样,但引用不同[1,2],[1,2]];// 你的去重策略是什么?提示:可能需要结合多种方法,或者自定义比较函数!
结语
数组去重是前端开发中的基础但重要技能。不同的场景需要不同的方法,就像工具箱里的不同工具,各有各的用途。掌握这些方法,不仅能提高代码效率,还能让你的解决方案更加优雅。
希望这篇博客能帮助你在下次遇到数组去重问题时,能够自信地选择最合适的方法!