JS中的数组去重策略

245 阅读1分钟

No.1

ES6更新前的重用去重方式。主要思路:双重循环+splice()方法

var arr = [1, 1, 2, 2, 3, 3, 5, 5, null, null, NaN, NaN, {}, {}]
for (let i = 0; i < arr.length - 1; i++) {
    for (let j = i + 1; j < arr.length; j++) {
        if (arr[i] === arr[j]) {
            arr.splice(j, 1)
            j--  //注意这里要回退一个
        }
    }
}
console.log(arr);
//[1, 2, 3, 5, null, NaN, NaN, {}, {}]
//无法去重NaN和{},可以去重null

No.2

JS中最简单的去重方式。主要思路:Set+扩展运算符(...)

var arr = [1, 1, 2, 2, 3, 3, 5, 5, null, null, NaN, NaN, {}, {}]
console.log([...new Set(arr)]);

//利用了Set中的元素是唯一的特性
//另外转化为数组的方法还有Array.from(),所以console.log(Array.from(new Set(arr)))也是OK的
//[1, 2, 3, 5, null, NaN, {}, {}]
//无法对{}去重,可以对null、NaN去重

No.3

利用JS中判断元素存在与否的特性。主要思路:一层循环+indexOf/includes

var arr = [1, 1, 2, 2, 3, 3, 5, 5, null, null, NaN, NaN, {}, {}]
var array = []
for (let i = 0; i < arr.length; i++) {
    if (array.indexOf(arr[i]) === -1) {
        array.push(arr[i])
    }
}
console.log(array);
//[1, 2, 3, 5, null, NaN, NaN, {}, {}]
//无法对NaN和{}去重,可以对null去重   
var arr = [1, 1, 2, 2, 3, 3, 5, 5, null, null, NaN, NaN, {}, {}]
var array = []
for (let i = 0; i < arr.length; i++) {
    if (!array.includes(arr[i])) {
        array.push(arr[i])
    }
}
console.log(array);
//结果与上述一模一样

No.4

如果你不想写循环...。试试这样:filter+indexOf

var arr = [1, 1, 2, 2, 3, 3, 5, 5, null, null, NaN, NaN, {}, {}]
var array = []
array = arr.filter((item, index) => {
    //每次迭代过程中,index是不断变化的,但item第一次出现的位置是早已固定了的
    return arr.indexOf(item) === index  
})
console.log(array);
//[1, 2, 3, 5, null, NaN, {}, {}]
//无法对{}去重,可以对null、NaN去重

No.5

上面几种方法都是存在瑕疵。要不瞅瞅这种完美去重的方法:filter+hasOwnProperty

var arr = [1, 1, 2, 2, 3, 3, 5, 5, null, null, NaN, NaN, {}, {}]
var array = []
var obj = {}
array = arr.filter(item => {
    //console.log(typeof item + item); 不知道(typeof item + item)啥意思的,可以打印出来瞧瞧,瞬间就懂了
    if (obj.hasOwnProperty(typeof item + item)) {
    return false
  } else {
    obj[typeof item + item] = true
    return true
  }
})
console.log(array);
////[1, 2, 3, 5, null, NaN, {}]
//主要借助了hasOwnPrototype()不会攀升原型链的特性。判断obj对象自身上是否存在某个数据类型+数据
//如果存在自然就返回false,然后给过滤掉咯;
//如果不存在则存入这个数据类型+数据,并返回true,表示不过滤。

写在最后:如你所见,使用时需要具体情况具体分析(浏览器兼容性/是否需要处理特殊元素)