JavaScript数组去重的几种方法
本文详细解析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等通过改变数组本身结构或依赖严格相等判断的方法,在处理对象时往往不可行。
以上即为本文的全部内容,希望这些内容对您的学习或工作有所帮助,感谢支持。
JS处理含Emoji或中文的字符串转数组乱码问题
2026-11-05 16:12:28
JS怎么使用展开运算符合并对象
2026-11-05 14:42:18
ES6+环境下判断JS对象为空的简洁写法
2026-11-05 12:12:23
怎么通过replacer函数自定义JS中JSON的格式化输出
2026-11-05 11:19:44
JS正则表达式基础:字面量与RegExp构造函数的区别及常用元字符
2026-11-05 11:16:58
相关标签:
