JavaScript陣列去重方法總結

鹽酸不是酸發表於2019-04-05

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

相關文章