JS数组去重详情

编辑: admin 分类: javascript 发布时间: 2021-11-17 来源:互联网
目录
  • 1 测试用例
  • 2 JS 数组去重4大类型
    • 2.1 元素比较型
      • 2.1.1 双层 for 循环逐一比较(es5常用)
      • 2.1.2 排序相邻比较
    • 2.2 查找元素位置型
      • 2.2.1 indexOf
      • 2.2.2 findIndex
    • 2.3 元素是否存在型
      • 2.3.1 includes
      • 2.3.2 some
    • 2.4 依托数据结构特性
      • 2.4.1 Map
      • 2.4.2 Set(ES6 最常用)
  • 3 补充

    1 测试用例

    // 测试用例
    const a = {};
    const b = { c: 1 };
    const array = [
      1, 1, "1", "1",
      {}, {}, { c: 1 }, { c: 1},
      a, a, b, b, 
      [], [], [1], [1],
      undefined, undefined,
      null, null,
      NaN, NaN,
    ];
    
    

    2 JS 数组去重4大类型

    2.1 元素比较型

    此类型通过数组元素之间进行比较来去重

    2.1.1 双层 for 循环逐一比较(es5常用)

    使用双层for循环逐一比较数组元素,用splice方法去除重复的元素

    // 双层for循环
    function uniq1(arr) {
        for (let i = 0; i < arr.length; i++) {
            for (let j = i + 1; j < arr.length; j++) {
                if (arr[i] === arr[j]) {
                    arr.splice(j, 1)
                    j--
                }
            }
        }
        return arr
    }
    
    // 去重结果
    // [1,'1',{},{},{c:1},{c:1},{},{c:1},[],[],[1],[1],undefined,null,NaN,NaN]
    

    通过对比去重前后结果,重复的NaN没有去掉,因为NaN === NaNfalse

    2.1.2 排序相邻比较

    使用sort()方法对数组元素进行排序,然后比较相邻元素,用splice方法去除重复的元素。

    function uni2(arr) {
        arr.sort();
        for (let i = 0; i < arr.length - 1; i++) {
            arr[i] === arr[i + 1] && arr.splice(i + 1, 1) && i--;
        }
        return arr;
    }
    
    
    

    也可以创建新数组,将不重复的元素放入新数组中

    function uniq3(arr) {
        arr = arr.sort()
        const newArr = [arr[0]]
        for (let i = 1; i < arr.length; i++) {
            if (arr[i] !== arr[i - 1]) {
                newArr.push(arr[i])
            }
        }
        return newArr
    }
    
    // 去重结果
    // [[],[],1,'1',[1],[1],NaN,NaN,{},{},{c:1},{c:1},{},{c:1},null,undefined]
    

    重复的NaN没有去掉,因为NaN === NaN为false
    sort
    默认排序顺序是将元素转换为字符串,对象转换为字符串都是[object Object] ,所以sort方法不能对数组中的对象进行排序,也就有可能无法去除重复的对象,除非重复的对象本就相邻

    2.2 查找元素位置型

    此类型通过查找元素第一次出现的位置来去重

    2.2.1 indexOf

    通过indexOf查找当前元素第一次出现的位置是否为当前位置,若是,则放入新数组

    function uniq4(arr) {
        let res = []
        for (let i = 0; i < arr.length; i++) {
            if (arr.indexOf(arr[i]) === i) {
                res.push(arr[i])
            }
        }
        return res
    }
    
    // 去重结果
    // [1,'1',{},{},{c:1},{c:1},{},{c:1},[],[],[1],[1],undefined,null]
    

    同样,因为NaN === NaNfalse,所以用indexOf查找NaN结果总是-1,从而在新数组中不会有NaN

    2.2.2 findIndex

    通过findIndex查找当前元素第一次出现的位置是否为当前位置,若是,则放入新数组

    function uniq5(arr) {
        let res = []
        for (let i = 0; i < arr.length; i++) {
            if (arr.findIndex(item => item === arr[i]) === i) {
                res.push(arr[i])
            }
        }
        return res
    }
    // 去重结果
    // [1,'1',{},{},{c:1},{c:1},{},{c:1},[],[],[1],[1],undefined,null]
    
    
    

    同样,因为NaN === NaNfalse,所以用findIndex查找NaN结果总是-1,从而在新数组中不会有NaN

    2.3 元素是否存在型

    此类型通过判断在新数组中是否存在当前元素来去重

    2.3.1 includes

    includes方法用来判断一个数组是否包含一个指定的值

    function uniq6(arr) {
        let res = []
        for (let i = 0; i < arr.length; i++) {
            if (!res.includes(arr[i])) {
                res.push(arr[i])
            }
        }
        return res
    }
    // 去重结果
    // [1,'1',{},{},{c:1},{c:1},{},{c:1},[],[],[1],[1],undefined,null,NaN]
    
    
    

    includes使用零值相等算法来确定是否找到给定的元素,所以可以判断NaN是否在新数组中存在

    2.3.2 some

    some方法用来测试数组中是否至少有1个元素通过了被提供的函数测试

    function uniq7(arr) {
        let res = []
        for (let i = 0; i < arr.length; i++) {
            if (!res.some(item => item === arr[i])) {
                res.push(arr[i])
            }
        }
        return res
    }
    // 去重结果
    // [1,'1',{},{},{c:1},{c:1},{},{c:1},[],[],[1],[1],undefined,null,NaN,NaN]
    
    
    

    同样,这里仍旧使用了===来比较元素,因为NaN === NaNfalse,所以新数组中会有多个NaN

    2.4 依托数据结构特性

    此类型通过ES6提供的数据结构MapSet本身不可重复特性来去重

    2.4.1 Map

    ES6提供的Map结构可以用各种类型的值(包括对象)当作键,且键是唯一的

    function uniq8(arr) {
        const map = new Map()
        for (let i = 0; i < arr.length; i++) {
            !map.has(arr[i]) && map.set(arr[i], true)
        }
        return [...map.keys()]
    }
    // 去重结果
    // [1,'1',{},{},{c:1},{c:1},{},{c:1},[],[],[1],[1],undefined,null,NaN]
    
    
    

    map.has方法对NaN也有效

    2.4.2 Set(ES6 最常用)

    Set结构的成员的值都是唯一的,没有重复的值。

    function uniq9(arr) {
        return [...new Set(arr)]
    }美国多ip服务器http://www.558idc.com/mgzq.html
    
    // 去重结果
    // [1,'1',{},{},{c:1},{c:1},{},{c:1},[],[],[1],[1],undefined,null,NaN]
    
    

    3 补充

    上面所说的方法可以使用不同的Api进行改动,比如使用splice方法去除数组元素的地方,我们可以通过filter方法来过滤数组得到新数组;

    再比如includes的方法中不用for循环遍历数组,通过reduce方法来代替等等。

    总之,方法有很多,但是万变不离其宗

    有些去重方法对NaN无效,因为NaN === NaNfalse,如果有需求,可以使用Object.is(NaN, NaN)true来进行修改

    实际应用中,最常用的方法就是使用Set,也可以使用第三方库lodash来处理

    到此这篇关于JS数组去重详情的文章就介绍到这了,更多相关JS数组去重内容请搜索hwidc以前的文章或继续浏览下面的相关文章希望大家以后多多支持hwidc!