前言
有时候我们做项目的时候往往会需要把数组里面一些重复的项去掉,但是原生JS有排序,有筛选等等,但是就是没有数组去重怎么办呢?
这能怎么办,自己手动实现嘛。
数组不像对象和hash有唯一的标志特征(key)。所以,数组去重的核心就是【1】数组内元素互相比较,然后放入新的数组中。【2】参照对象构建一个唯一的特征标志,然后放入新数组中。以下就是依照这种思路产生的方法。【3】数组中含对象的去重方式我采用使用JSON.stringify()
将对象转换成JSON字符串进行比较的方式。
1.最基础的去重:双重遍历
双重遍历的核心就是依据【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():存在唯一性
在一个对象里面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 }
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 }
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.总结
实现数组的去重,要么通过元素对比,要么设置特殊标志识别。元素对比的思路有2种:一种是和原数组一一对比;另一种和新的数组对比。
如果要实现含对象的数组去重,一般使用遍历的方式,包括使用遍历类的方法(map、forEach、reduce等)。像Set、sort等通过改变数组的方式一般是不可行的。
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对找一找教程网的支持。