zoukankan      html  css  js  c++  java
  • 从一个数组中删除重复对象

    1、简单的数组去重
     
    可以借用数组的 filter()方法和indexOf()方法,由于 indexOf(item) 返回的是数组中第一个item的索引,所以可以借此实现数组元素去重的功能
    const names = ['张三', '李四', '张三'];
    
    function getUnique(arr) {
      return arr.filter((item, index) => arr.indexOf(item) === index)
    }
    
    getUnique(names); // ["张三", "李四"]
    2、从数组中删除重复的对象
     
    如果数组的元素是对象,就不那么简单了。众所周知,对象是引用类型,比较两个对象不是比较对象的属性和值而是比较对象的地址值
     
    如下例所示,数组首尾两个元素看起来是一模一样的,但是用前面的方法没法去重
    const goodsList = [
      {
        goodsCode: '2611201047G',
        goodsName: '华为畅享9 Plus 4GB+128GB 极光紫 双卡 全网通版 JKM-AL00'
      },
      {
        goodsCode: '2611201418G',
        goodsName: 'HUAWEInova5i 8GB+128GB 苏音蓝 全网通版'
      },
      {
        goodsCode: '2611201047G',
        goodsName: '华为畅享9 Plus 4GB+128GB 极光紫 双卡 全网通版 JKM-AL00'
      }
    ]
    
    
    getUnique(goodsList);  // 返回的依然是goodsList
    这里可以借助JSON.stringify() 方法把一个对象转成string类型来做比较
    function getUnique2(arr) {
      const map = {};
      // 1、把数组元素作为对象的键存起来(这样就算有重复的元素,也会相互替换掉)
      arr.forEach(item => map[JSON.stringify(item)] = item);
      
      // 2、再把对象的值抽成一个数组返回即为不重复的集合
      return Object.keys(map).map(key => map[key])
    }
    
    getUnique2(goodsList); 
    /*
      [
        {goodsCode: "2611201047G", goodsName: "华为畅享9 Plus 4GB+128GB 极光紫 双卡 全网通版 JKM-AL00"},
        {goodsCode: "2611201418G", goodsName: "HUAWEInova5i 8GB+128GB 苏音蓝 全网通版"}
      ]
    */

    但是这里有一个问题,假如把 goodsList 中最后一个元素的 goodsCode 和 goodsName调换一下顺序,就没法去重了

    const goodsList = [ // 注意比较首尾元素对象中内部属性的顺序
      {
        goodsCode: '2611201047G',
        goodsName: '华为畅享9 Plus 4GB+128GB 极光紫 双卡 全网通版 JKM-AL00'
      },
      {
        goodsCode: '2611201418G',
        goodsName: 'HUAWEInova5i 8GB+128GB 苏音蓝 全网通版'
      },
      { 
        goodsName: '华为畅享9 Plus 4GB+128GB 极光紫 双卡 全网通版 JKM-AL00',
        goodsCode: '2611201047G'
      }
    ]
    
    function getUnique3(arr) {
      const map = {};
    
      arr.forEach(item => {
        const obj = {};
        // 1、把数组中的元素(对象)的键名抽成一个数组然后排序
        // 2、生成一个按照键名排序好的对象
        Object.keys(item).sort().map(key => obj[key] = item[key]);
    
        // 3、把新生成的对象作为对象的键存起来
        map[JSON.stringify(obj)] = item;
      });
      
      // 4、再把新对象的键名抽成一个数组返回即为不重复的集合
      return Object.keys(map).map(key => JSON.parse(key));
    }
    
    console.log(getUnique3(goodsList)); 
    /*
      [
        {goodsCode: "2611201047G", goodsName: "华为畅享9 Plus 4GB+128GB 极光紫 双卡 全网通版 JKM-AL00"},
        {goodsCode: "2611201418G", goodsName: "HUAWEInova5i 8GB+128GB 苏音蓝 全网通版"}
      ]
    */
    除了上面那样,通过把对象的属性名排序来处理以外,还可以借助JSON.stringify()的replacer参数来实现
    JSON.stringify(value[, replacer [, space]])
    
    value:将要序列化成 一个 JSON 字符串的值。
    
    replacer:如果 replacer 是一个数组,数组的值代表将被序列化成 JSON 字符串的属性名

    也就是说,可以通过 JSON.stringify的第二个参数指定按一定的顺序来序列化,例如

    const goodsList = [ // 注意比较首尾元素对象中内部属性的顺序
      {
        goodsCode: '2611201047G',
        goodsName: '华为畅享9 Plus 4GB+128GB 极光紫 双卡 全网通版 JKM-AL00'
      },
      {
        goodsCode: '2611201418G',
        goodsName: 'HUAWEInova5i 8GB+128GB 苏音蓝 全网通版'
      },
      { 
        goodsName: '华为畅享9 Plus 4GB+128GB 极光紫 双卡 全网通版 JKM-AL00',
        goodsCode: '2611201047G'
      }
    ]
    
    console.log(JSON.stringify(goodsList, ['goodsName', 'goodsCode']));
    /*
      [
        {"goodsName":"华为畅享9 Plus 4GB+128GB 极光紫 双卡 全网通版 JKM-AL00","goodsCode":"2611201047G"},
        {"goodsName":"HUAWEInova5i 8GB+128GB 苏音蓝 全网通版","goodsCode":"2611201418G"},
        {"goodsName":"华为畅享9 Plus 4GB+128GB 极光紫 双卡 全网通版 JKM-AL00","goodsCode":"2611201047G"}
      ]
    */

    由此可见,只需要把 getUnique2() 稍作修改,就可以产生最佳的解决方案了

    function getUnique2(arr) {
      const map = {};
      // 1、把数组元素作为对象的键存起来(这样就算有重复的元素,也会相互替换掉)
      arr.forEach(item => map[JSON.stringify(item, ['goodsCode', 'goodsName'])] = item);
      
      // 2、再把新对象的键名抽成一个数组返回即为不重复的集合
      return Object.keys(map).map(key => JSON.parse(key))
    }
    
    console.log(getUnique2(goodsList)); 
    /*
      [
        {goodsCode: "2611201047G", goodsName: "华为畅享9 Plus 4GB+128GB 极光紫 双卡 全网通版 JKM-AL00"},
        {goodsCode: "2611201418G", goodsName: "HUAWEInova5i 8GB+128GB 苏音蓝 全网通版"}
      ]
    */
  • 相关阅读:
    iOS很重要的 block回调
    怎样写具体设计文档
    ORM框架
    RapidXml用法
    【Android Training
    ORACLE触发器具体解释
    LeetCode 131 Palindrome Partitioning
    Git管理工具对照(GitBash、EGit、SourceTree)
    Android下将图片载入到内存中
    怎样破解邮箱password
  • 原文地址:https://www.cnblogs.com/rogerwu/p/12709172.html
Copyright © 2011-2022 走看看