zoukankan      html  css  js  c++  java
  • js 数组深度去重

      在日常开发中难免会遇到数组去重的难题,最近,正是给一个数组去重的难题难到了。作为开发者的我们,一旦遇到问题必然就是谷歌,百度,MDN....搜索一波,但是,这些地方都没有找到我想要的答案。或许看到这你会开喷了,咋没有啊,网上一大堆去重方法,但是,这里的需求要的是深度去重,也就是说,引用类型也要去掉!!这时你会发现很多方法都不管用了,看了一波度娘的答案,绝大部分的都是循环,索引相等的方法去重,而且举的例子都是基本数据类型的去重,如果手上拿的是一个全是引用类型的数组,你会发现这些方法都没用了。在讲正题之前,先讲一个基本数据类型去重的方法:

    arr = Array.from(new Set(arr))

    注意:该方法也只能用在全是基本类型的数组上,一旦有重复的引用类型的数据就无法过滤了。

      回到正题上,怎么给引用类型的数组去重,先定义下面一个方法:

    function getType(target) {
         return Object.prototype.toString.call(target).slice(8,-1)
    }

    该方法用于区分对象和数组,如果是对象,则返回的是 Object ,如果是数组,则返回 Array。

    定义方法,用于检查两个对象里面的内容是否一致,若一致,返回 true ,否则返回 false:

    function objUnique(a,b) {
         if(getType(a) !== 'Object' && getType(b) !== 'Object'){
             return false
         }
         let testList = Object.keys(a)
         for(let i = 0;i < testList.length;i++){
             let propName = testList[i]
             if(getType(a[propName]) === 'Object' && getType(b[propName]) === 'Object'){
                 objUnique(a[propName],b[propName])
             }else if(getType(a[propName]) === 'Array' && getType(b[propName]) === 'Array'){
                 arrUnique(a[propName],b[propName])
             }else if(a[propName] !== b[propName]){
                 return false
             }
         }
         return true
    }

    定义方法,用于检测两个数组的内容是否一致,若一致返回 true,否则返回 false:

    function arrUnique(a, b) {
        if(getType(a) !== 'Array' && getType(b) !== 'Array'){
           return false
        }
        if(a.length !== b.length){
           return false
        }
        for(let i = 0;i < a.length;i++){
           if(getType(a[i]) === 'Object' && getType(b[i]) === 'Object'){
                objUnique(a[i],b[i])
           }else if(getType(a[i]) === 'Array' && getType(b[i]) === 'Array'){
                arrUnique(a[i],b[i])
           }else if(a[i] !== b[i]){
                return false
           }
        }
        return true
    }

    最后,讲目标数组所有元素进行分类(当然,这里忽略了元素的顺序,如果数组元素没有顺序要求,或者数组的元素全是同一种类型的情况,则可以正常使用,否则另寻办法),分别将基本类型,对象,数组放入一个容器中,然后用上面的三个方法分别对里面的所有元素进行去重,再将三个数组重新组合:

    function unique(arr) {
        if(getType(arr) !== 'Array'){
            return null
        }
        // 基本数据类型容器
        let commonList = []
        // 对象收纳容器
        let objList = []
        // 数组收纳容器
        let arrList = []
    
        // 数据分类
        arr.forEach(item => {
            if(getType(item) === 'Object'){
                objList.push(item)
            }else if(getType(item) === 'Array'){
                arrList.push(item)
            }else{
                commonList.push(item)
            }
        })
        // 基本数据类型去重
        commonList = Array.from(new Set(commonList))
        // 对象收纳容器去重
        for(let i = 0;i < objList.length;i++){
            for(let j = i + 1;j < objList.length;j++){
                if(objUnique(objList[i],objList[j])){
                    objList.splice(j,1)
                    j--
                }
            }
        }
        // 数组收纳容器去重
        for(let i = 0;i < arrList.length;i++){
            for(let j = i + 1;j < arrList.length;j++){
                if(arrUnique(arrList[i],arrList[j])){
                    arrList.splice(j,1)
                    j--
                }
            }
        }
        // 合并收纳容器
        return [...commonList,...objList,...arrList]
    }

    这里,再强调一次,如果数组元素没有顺序要求,或者数组中所有元素都是同一类型(都是对象或都是数组),才可使用。另外,如果还有更好的方法欢迎补充,谢谢。

    github地址:https://github.com/JonasVon/unique.git

  • 相关阅读:
    范仁义html+css课程---7、表单
    范仁义html+css课程---6、表格
    范仁义html+css课程---5、列表
    范仁义html+css课程---4、文本标签
    范仁义html+css课程---3、图片和超链接
    react项目如何运行
    maven search
    PowerDesigner中Name与Code同步的问题
    PowerDesigner跟表的字段加注释
    MobilePhone正则表达式
  • 原文地址:https://www.cnblogs.com/jonas-von/p/9595444.html
Copyright © 2011-2022 走看看