测试用例

var arr = [1,1,'1','1',0,0,'0','0',undefined,undefined,null,null,NaN,NaN,{},{},[],[],/a/,/a/]

indexOf

function unique(arr){
    var temp = []
    for(var i=0;i<arr.length;i++){
        if(arr.indexOf(arr[i]) === i){
            temp.push(arr[i])
        }
    }
    return temp
}

console.log(unique(arr))
> [ 1, '1', 0, '0', undefined, null, {}, {}, [], [], /a/, /a/ ]
  • NaN丢失


function unique(arr){
    var temp = []
    arr.forEach(function(item){
        if(temp.indexOf(item) === -1){
            temp.push(item)
        }
    })
    return temp
}
console.log(unique(arr))
> [ 1, '1', 0, '0', undefined, null, NaN, NaN, {}, {}, [], [], /a/, /a/ ]
  • NaN重复


  • indexOf认为NaN与NaN是不重复的

includes

function unique(arr){
    var temp = []
    for(var i=0;i<arr.length;i++){
        if(!temp.includes(arr[i])){
            temp.push(arr[i])
        }
    }
    return temp
}

console.log(unique(arr))
>  [1, "1", 0, "0", undefined, null, NaN, {}, {}, [], [], /a/, /a/]
  • includes认为NaN和NaN是重复的

===

function unique(arr){
    var temp = []
    var isRepeat = false
    for(var i=0;i<arr.length;i++){
        isRepeat = false
        for(var j=i+1; j<arr.length;j++){
            if(arr[i]===arr[j]){
                isRepeat = true
                break
            }
        }
        if(!isRepeat){
            temp.push(arr[i])
        }
    }
    return temp
}
console.log(unique(arr))

> [1, "1", 0, "0", undefined, null, NaN, NaN, {}, {}, [], [], /a/,/a/]
  • NaN重复

使用对象实现数组去重及改进

function unique(arr){
    var obj = {}
    var temp = []
    for(var i=0;i<arr.length;i++){
        if(!obj[arr[i]]){
            obj[arr[i]] = 1
            temp.push(arr[i])
        }
        
    }
    return temp
}
console.log(unique(arr))
> [ 1, 0, undefined, null, NaN, {}, [], /a/ ]
  • 无法区分隐式类型转换成字符串后一样的值,比如1和'1'

  • 无法处理复杂数据类型,比如对象(因为对象作为key会变成[object Object])

改进1

function unique(arr){
    var obj = {}
    var temp = []
    var key
    for(var i=0;i<arr.length;i++){
        key = typeof arr[i] + arr[i]
        if(!obj[key]){
            obj[key] = 1
            temp.push(arr[i])
        }
        
    }
    return temp
}
console.log(unique(arr))
> [ 1, '1', 0, '0', undefined, null, NaN, {}, [], /a/ ]

改进2

function unique(arr){
    var obj = {}
    var temp = []
    var key
    for(var i=0;i<arr.length;i++){
        key = typeof arr[i] + JSON.stringify(arr[i])
        if(!obj[key]){
            obj[key] = 1
            temp.push(arr[i])
        }
        
    }
    return temp
}
console.log(unique(arr))
> [ 1, '1', 0, '0', undefined, null, NaN, {}, [] ]

map

function unique(arr){
    var temp = []
    var map = new Map()
    for(var i=0; i<arr.length;i++){
        if(!map.get(arr[i])){
            map.set(arr[i],1)
            temp.push(arr[i])
        }
    }
    return temp
}
console.log(unique(arr))
> [ 1, '1', 0, '0', undefined, null, NaN, {}, {}, [], [], /a/, /a/ ]

set

function unique(arr){
    var set = new Set(arr)
    return Array.from(set)
}
console.log(unique(arr))
> [ 1, '1', 0, '0', undefined, null, NaN, {}, {}, [], [], /a/, /a/ ]

各种方法比较

clipboard.png

总结

数组去重需要根据场景选择合适的去重方法,没有固定的答案。

参考资料

谈JavaScript数组去重


jhhfft
590 声望40 粉丝

Write the Code. Change the World.