陣列不像物件和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等通過改變陣列的方式一般是不可行的。