JavaScript数组去重的几种方法

作者:拾光

时间:2026-10-23

浏览:557

本文详细解析JavaScript中实现数组去重的多种方案,涵盖双重遍历、排序比较、哈希表、indexOf、Map/forEach以及ES6的Set数据结构。重点探讨含对象数组的去重难点,对比各方法的代码复杂度、时间效率及适用场景,帮助开发者根据实际需求选择最优解。

文章目录

引言

前言

在项目开发过程中,经常遇到需要去除数组中重复元素的需求。原生JavaScript提供了排序、筛选等功能,却未直接提供数组去重的内置方法。

面对这一缺失,我们需要手动实现去重逻辑。

数组不像对象和hash有唯一的标志特征(key)。所以,数组去重的核心就是【1】数组内元素互相比较,然后放入新的数组中。【2】参照对象构建一个唯一的特征标志,然后放入新数组中。以下就是依照这种思路产生的方法。【3】数组中含对象的去重方式我采用使用JSON.stringify()将对象转换成JSON字符串进行比较的方式。

基础双重遍历法

1.最基础的去重:双重遍历

该方法的核心逻辑基于上述第一种思路,即通过嵌套循环,取出一个元素并与剩余所有元素逐一比较。若该元素与其余所有元素均不相等,则判定为唯一值。


let a=[{a:1},{b:2},{c:3},{a:1},{d:2}]
let c=[1,2,3,4,5,6,1,2,3]
function unique(arr){
 let b=[]
 for(let i=0;i<arr.length;i++){
 let unexit=true
 for(let j=i+1;j<arr.length;j++){
  if(JSON.stringify(arr[i])===JSON.stringify(arr[j])){
  unexit=false
  break
  }
  else{
  unexit=true
  }
 }
 if(unexit){
  b.push(arr[i])
 }
 }
 return b
}

针对数组中包含对象的情况,同样采用JSON.stringify()将其转换为JSON字符串进行比较,此处不再赘述。双重遍历的主要缺点是时间复杂度较高。此外,上述代码执行后,去重结果的顺序可能会发生改变。若需保持原有顺序,建议在去重时重新声明一个新数组(var new=old.reverse()),通过获取反向数组后再调用reverse()方法还原顺序。之所以不直接对原数组取反,是因为reverse()会修改原数组,可能引发副作用。

排序与相邻元素去重

2.Array.prototype.sort():相邻元素去重

相邻元素去重的关键在于Array.sort()能够对数组进行排序。排序后,相等的元素会相邻排列,通过比较相邻元素即可实现去重(思路【1】)。


let c=[1,2,3,4,5,6,1,2,3]
function unique(arr){
 let Arr=arr.sort()
 let b=[]
 for(let i=0;i<Arr.length;i++){
 if(Arr[i]!==Arr[i+1]){
  b.push(Arr[i])
 }
 }
 return b
}

Array.prototype.sort()方法还可以配合array.sort((a,b)=>{a.key-b.ky})进行对象排序,但前提是数组中的对象必须存在相同的key值。

利用对象键唯一性去重

3.Object.keys():存在唯一性

在JavaScript对象中,key值是唯一的。因此,可以通过遍历数组,为每个元素生成一个唯一的标志(key),利用该标志进行去重(思路【2】)。


let a=[{a:1},{b:2},{c:3},{a:1},{d:2}]
let c=[1,2,3,4,5,6,1,2,3]
function unique(arr){
 let b=[]
 let hash={}
 for(let i=0;i<arr.length;i++){
 if(!hash[JSON.stringify(arr[i])]){
  hash[JSON.stringify(arr[i])]=true
  b.push(arr[i])
 }
 }
 return b
}

indexOf改良法

4.双重遍历去重改良之:indexOf

双重遍历的基本思路是取出一个元素,再通过循环遍历数组进行逐一比较。如果存在一种方式无需再次遍历整个数组即可完成判断,则可有效降低复杂度。

indexOf方法返回给定元素在数组中首次出现的位置,若未找到则返回-1。我们新建一个空数组(arry),若arry.indexOf(数组元素)返回-1,则说明该元素在arry中不存在,可将其加入。


let c=[1,2,3,4,5,6,1,2,3]
function unique(arr){
 let b=[]
 for(let i=0;i<arr.length;i++){
 if(b.indexOf(arr[i])==-1){
  b.push(arr[i])
 }
 }
 return b
}

需要注意的是,indexOf方法适用于字符串或基本类型值的查找。对于对象,由于对象转换为字符串后通常都显示为{object,object},导致无法通过此方法有效比较,因此该方法不适用于含对象的数组去重。

遍历方法改写

5.循环遍历之:map()/forEach()

map()和forEach()均可用于数组遍历。因此,上述多种去重方法均可通过map()或forEach()进行改写。此处仅展示简单的改写示例,其他方法的改写逻辑可参照执行。


let c=[1,2,3,4,5,6,1,2,3]
function unique(arr){
 let b=[]
 arr.forEach(res=>{
 if(b.indexOf(res)==-1){
  b.push(res)
 }
 })
 return b
}

ES6 Set数据结构应用

6.ES6:Set数据结构

Set数据结构类似于数组,但其成员值唯一,不允许重复。它可以接收一个数组作为参数,例如:let a=[1,2,3,1,2]  Set(a)=>1,2,3 。因此,可以直接利用Set()构造函数实现去重。


let c=[1,2,3,4,5,6,1,2,3]
function unique(arr){
 let b=new Set(arr)
 let c=Array.from(b)
 return c
}

然而,Set去重不适用于包含对象的数组。因为Set的去重机制基于严格相等(===)判断,数组中的对象即使数值内容相同,其内存地址也不同。因此,Set无法实现含对象数组的去重。

方法总结与适用场景

7.总结

实现数组去重主要有两种途径:通过元素对比或设置特殊标志识别。元素对比的思路包括两种:一是与原数组中的其他元素逐一比对;二是与新构建的数组进行比对。

若需实现包含对象的数组去重,通常建议使用遍历方式,包括使用map、forEach、reduce等遍历类方法。而像Set、sort等通过改变数组本身结构或依赖严格相等判断的方法,在处理对象时往往不可行。

以上即为本文的全部内容,希望这些内容对您的学习或工作有所帮助,感谢支持。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章