解锁数组去重的多种姿势

197 阅读1分钟

不管在实际工作还是面试场景中数组去重都非常重要,总结一下

最简单场景
const arr = [1, 1, 2, 2, 3, 3];
  • 双重循环
const uniqueArr = (arr) => {
    const res = [];
    for (var i = 0; i < arr.length; i += 1) {
        for (var j = 0; j < res.length; j += 1) {
            if (arr[i] === res[j]) break;
        }
        if (j === res.length) {
            res.push(arr[i])
        }
    }
    return res
}
console.log(uniqueArr(arr)); // [1,2,3]
  • indexOf配合单层循环
const uniqueArr = (arr) => {
    const res = [];
    for (let i = 0; i < arr.length; i += 1) {
        if (res.indexOf(arr[i]) === -1) res.push(arr[i])
    }
    return res
}
  • filter 也可以
const uniqueArr = (arr) => {
    return arr.filter((item, index, array) => {
    if (array.indexOf(item) === index) return true
    })
}
有特殊值的场景
const arr = [1, 1, NaN, NaN]

由于 NaN===NaN 返回 false,因此使用 indexOf 判断的方式无法去重这种特殊值,此时可以考虑使用较新版本的 API 或者数据结构。

  • includes 配合遍历
const uniqueArr = (arr) => {
    const res = [];
    for (let i = 0; i < arr.length; i += 1) {
        if (!res.includes(arr[i])) res.push(arr[i])
    }
    return res;
}
console.log(uniqueArr(arr)); // [1, NaN]
  • 使用 Set
const res = [...new Set(arr)];
有对象类型
const arr = [1,1,'1',2,2,'2',NaN,NaN,{},{}]

当数组元素含有如 {} 相同的多个元素时,使用上述方法无法去重,可使用对象键值对的方式

  • 对象键值对
const uniqueArr = (arr) => {
    const obj = {};
    return arr.filter(item => {
        if (!obj.hasOwnProperty(typeof item + item)) {
            obj[typeof item + item] = true;
            return true
        }
    })
}
console.log(uniqueArr(arr)); // [ 1, "1", 2, "2", NaN, {} ]

将对象的键名构造成 typeof item + item 而非简单的 item 是为了处理像1 和 '1' 的情况

  • obj 可以用来去重,Map 当然也行
const uniqueArr = (arr) => {
    const map = new Map();
    return arr.filter(item => {
            if (!map.has(typeof item + item)) {
                map.set(typeof item + item, true);
                return true;
         }
    })
}

此外还可采用先排序再去重等方式进行优化

本文使用 mdnice 排版