js数组去重(包括对象数组去重)

2019.08.02补:
对象数组建议直接循环然后使用工具库(lodash)的深比较,评论里也有指出,文章的方法有些取巧了 生产环境不要这么玩~。


  • 方法一:利用ES6的Array.from()/扩展运算符 以及 Set

    Array.from(): The Array.from() method creates a new Array instance from an array-like or iterable object.

    该方法接收两个参数要转换的非数组对象,对每个元素进行处理的方法(可选).在js中,有很多类数组对象(array-like object)和可遍历(iterable)对象(包括ES6新增的数据结构Set和Map),常见的类数组对象包括document.querySelectorAll()取到的NodeList,以及函数内部的arguments对象。它们都可以通过Array.from()转换为真正的数组,从而使用数组的方法。事实上只要对象具有length属性,就可以通过Array.from()转换为真正的数组。

    Set:A collection of unique values that may be of any type.

    Set:一个可以是任何类型的独一无二的值的集合.

      function unique(arr){
          return Array.from(new Set(arr));
      }
    

    你也可以这样写:

      function unique(arr){
          return [...new Set(arr)];
      }
    
  • 方法二:遍历数组,建立新数组,利用indexOf判断是否存在于新数组中,不存在则push到新数组,最后返回新数组

    Determines the index of the specific IThing in the list.

    indexOf() :方法可返回某个指定的字符串值在字符串中首次出现的位置。如果没有则返回-1

     function unique(arr){
         var newArr = [];
         for(var i in arr) {
             if(newArr.indexOf(arr[i]) == -1) {
                 newArr.push(arr[i])
             }
         }
         return newArr;
     }
    
  • 方法三:遍历数组,利用object对象的key值保存数组值(key不重复),判断数组值是否已经保存在object中,未保存则push到新数组并用object[arrayItem]=true的方式记录保存.

     function unique(arr) {  
       let hashTable = {};
       let newArr = [];
       for(let i=0,l=arr.length;i<l;i++) {
         if(!hashTable[arr[i]]) {
           hashTable[arr[i]] = true;
           newArr.push(arr[i]);
         }
       }
       return newArr;
     }
    
  • 方法四:先排序,新数组最后一项为旧数组第一项,每次插入判断新数组最后一项是否与插入项相等

    function unique(arr) {
        var newArr = [];
        var end; //end其实就是一道卡
        arr.sort();
        end = arr[0];
        newArr.push(arr[0]);
        for (var i = 1; i < arr.length; i++) {
            if (arr[i] != end) {
                newArr.push(arr[i]);
                end = arr[i]; //更新end
            }
        }
        return newArr;
    }
    

以上四种方法都是对于基本数据类型而言,如果换做对象数组就无能为力了,下面是对象数组的去重方法

  • 方法一:利用对象的键名不能重复的特点

     function unique(arr){
       let unique = {};
       arr.forEach(function(item){
         unique[JSON.stringify(item)]=item;//键名不会重复
       })
       arr = Object.keys(unique).map(function(u){ 
       //Object.keys()返回对象的所有键值组成的数组,map方法是一个遍历方法,返回遍历结果组成的数组.将unique对象的键名还原成对象数组
         return JSON.parse(u);
       })
       return arr;
     }
    
    
    
     map方法使用示例:
     var map = Array.prototype.map
     var a = map.call("Hello World", function(x) { return x.charCodeAt(0); })
     // a的值为[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]
    

    存在的问题:
    {x:1,y:2}与{y:2,x:1}通过JSON.stringify字符串化值不同,但显然他们是重复的对象.

  • 方法二:还是利用对象的键名无法重复的特点,必须知道至少一个对象数组中的对象的属性名

     var songs = [
             {name:"羽根",artist:"air"},
             {name:"羽根",artist:"air"},
             {name:"晴天",artist:"周杰伦"},
             {name:"晴天",artist:"周杰伦"},
             {artist:"周杰伦",name:"晴天"}
         ];
    
     function unique(songs){
         let result = {};
         let finalResult=[];
         for(let i=0;i<songs.length;i++){
             result[songs[i].name]=songs[i];
             //因为songs[i].name不能重复,达到去重效果,且这里必须知晓"name"或是其他键名
         }
         //console.log(result);{"羽根":{name:"羽根",artist:"air"},"晴天":{name:"晴天",artist:"周杰伦"}}
         //现在result内部都是不重复的对象了,只需要将其键值取出来转为数组即可
         for(item in result){
             finalResult.push(result[item]);
         }
         //console.log(finalResult);[{name:"羽根",artist:"air"},{name:"晴天",artist:"周杰伦"}]
         return finalResult;
     }
     
     console.log(unique(songs));
    
原数组(重复).png
result.png
finalResult.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,710评论 4 376
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,839评论 2 308
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,295评论 0 255
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,776评论 0 223
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,198评论 3 297
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,074评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,200评论 2 322
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,986评论 0 214
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,733评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,877评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,348评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,675评论 3 265
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,393评论 3 246
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,209评论 0 9
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,996评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,212评论 2 287
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 36,003评论 2 280

推荐阅读更多精彩内容