JS數組去重方法總結

JS數組去重

數組去重,做爲前端面試中的經典題,常常會被說起到。前端

本文就數組去重的方法,作了些許整理,方便理解與總結。面試

最原始的方法

在不借助JS數組的相關API的狀況下,咱們來看下數組去重最原始的實現方法:數組

var array = [1,1,'1','1']
function unique(array) {
    var res = []
    for (var i=0,arrlen=array.length;i<arrlen;i++) {
        for (var j = 0,reslen=res.length;j<reslen;j++) {
            if (array[i] === res[j]) {
                break
            }
        }
        if (j === reslen) {
            res.push(array[i])
        }
    }
    return res
}
console.log(unique(array)) //[1,'1']
複製代碼

在這個方法中,咱們使用循環嵌套,最外層循環 array,裏面循環 res,若是 array[i] 的值跟 res[j] 的值相等,就跳出循環,若是都不等於,說明元素是惟一的,這時候 j 的值就會等於 res 的長度,根據這個特色進行判斷,將值添加進 res。數據結構

這個最原始的方法,有着一個很明顯的優勢,兼容性好。ui

indexOf

藉助indexOf,咱們能夠稍稍簡化下內層循環:spa

var array = [1,1,'1','1']
function unique(array) {
    var res = []
    for (var i=0,len=array.length;i<len;i++) {
        var current = array[i]
        if (res.indexOf(current) === -1) {
            res.push(current)
        }
    }
    return res
}
console.log(unique(array)) // [1,'1']
複製代碼

filter

ES5提供了filter方法,咱們能夠藉助這個方法來簡化外層循環,好比改寫使用indexOf的去重方法:code

var array = [1,2,1,1,'1']
function unique(array) {
    var res = array.filter(function(item,index,array) {
        return array.indexOf(item) === index
    })
    return res
}
console.log(unique(array)) // [1,2,'1']
複製代碼

對象鍵值對去重

對象鍵值對去重是利用一個空的object對象,咱們把數組的值存成object對象的key值,好比讓object[array[item1]] = true,在判斷另外一個值object[array[item2]]存在的話,就說明該值是重複的:對象

var array1 = [1,2,1,2,1]
var array2 = [1, 2, 1, 1, '1'];
function unique(array) {
    var obj = {}
    return array.filter(function(item, index, array){
        return obj.hasOwnProperty(item) ? false : (obj[item] = true)
    })
}
console.log(unique(array1)) //[1,2]
console.log(unique(array2)) // [1, 2]
複製代碼

很明顯,如今這個方法是有問題,由於1和'1'是不一樣的,可是object[1]object['1']倒是同一個引用,由於對象的key值只能是字符串。字符串

那麼咱們使用 typeof item + item 拼成字符串做爲key值來避免這個問題:string

var array = [1,2,1,1,'1']
function unique(array) {
    var obj = {}
    return array.filter(function(item,index,array) {
        return obj.hasOwnProperty(typeof item+item)?false:(obj[typeof item+item] = true)
    })
}
console.log(unique(array)) //[1,2,'1']
複製代碼

But,若是數組項中若是存在對象時,好比{value:1}、{value:2},因爲typeof item + item的結果都會是object[object Object],不過咱們可使用JSON.stringfy()將對象序列化來避免相同的鍵值。因此可這樣改寫unique:

var array = [1,1,2,2,'1',{value: 1}, {value: 1}, {value: 2}]
function unique(array) {
    var obj = {}
    return array.filter(function(item, index, array){
        console.log(typeof item + JSON.stringify(item))
        return obj.hasOwnProperty(typeof item + JSON.stringify(item)) ? false : (obj[typeof item + JSON.stringify(item)] = true)
    })
}
console.log(unique(array)) // [1,2,'1',{value: 1}, {value: 2}]
複製代碼

ES6的Set對象和Map對象

Set對象是ES6中的新數據結構

根據MDN描述:

Set對象是值的集合,你能夠按照插入的順序迭代它的元素。 Set中的元素只會出現一次,即 Set 中的元素是惟一的。

也就是說,Set對象相似於數組,可是成員的值都是惟一的,沒有重複的值。

那麼藉助於Set,數組去重將變得異常簡單:

var array = [1, 2, 1, '1']
function unique(array) {
   return Array.from(new Set(array))
}
console.log(unique(array)) // [1, 2, "1"]
複製代碼

除此以外,咱們也可使用ES6中的Map對象來改寫unique:

var array = [1, 2, 1, '1'];
function unique(array) {
    const seen = new Map()
    return array.filter(function(item,index,array) {
        return !seen.has(item) && seen.set(item,1)
    })
}
console.log(unique(array)) //[1,2,'1']
複製代碼

不一樣數組去重方法結果的對比

假設有這樣一個數組:

var array = [1, 1, '1', '1', null, null, undefined, undefined, new String('1'), new String('1'), /a/, /a/, NaN, NaN];
複製代碼

用不一樣的數組去重方法,獲得的結果會有什麼不一樣嗎?

爲此,特意整理了一個列表,以表差別

方法 結果 說明
for循環 [1, "1", null, undefined, String, String, /a/, /a/, NaN, NaN] 對象和 NaN 不去重
indexOf [1, "1", null, undefined, String, String, /a/, /a/, NaN, NaN] 對象和 NaN 不去重
filter+indexOf [1, "1", null, undefined, String, String, /a/, /a/] 對象不去重 NaN 會被忽略掉
對象鍵值對去重 [1, "1", null, undefined, String, /a/, NaN] 所有去重
Set對象去重 [1, "1", null, undefined, String, String, /a/, /a/, NaN] 對象不去重 NaN 去重

至此,經常使用的數組去重方法都已展現在這裏,對於不一樣場景的使用也作了對比,方便理解與應用。

相關文章
相關標籤/搜索