JS中去重方法的探讨

说到去重有很多的实现,在ES6下根本不是问题:

let array=[1,2,3,4,1,2,3,4]
let result=null

// 利用 indexOf 只会返回第一次匹配结果的特性,过滤出第一次出现的项
result=array.filter((value,i)=>array.indexOf(value)===i)

// Set 对象数据结构决定了其元素的唯一性,再按需通过扩展符号将其转为数组
result=[...new Set(array)]

然而在ES6之前,兼顾性能的习惯性思路是基于 for 的遍历实现,copy 一个新的集合并与原始集合做遍历、比对,类似如下这种实现方法:

var uniq1=function(arr){
    var temp=[],
        item,
        i,n;

    for(i=0;i<arr.length;i+=1){ // 开始去重
        item=arr[i];
        temp.push(item);
        for(n=0;n<temp.length;n+=1){
            if(item===temp[n-1]){ // 如temp与arr中的元素重复则删除
                temp.splice(temp.length-1,1);
            }
        }
    }
    return temp;
};

上面这个例子会创建一个临时的空数组对象,在将元素逐个放入其中时与前一个元素作比对,如果值相同则从临时数组中剔除,直至遍历完所有比对对象……这个方法尽可能的优化了性能,但是出现了嵌套循环,代码实现逻辑复杂、对部分阅读者并不友好对吗?下面介绍一种或许可以减压并且性能表现不俗的实现方法。

先说说思路,我们习惯对数组元素逐一比较后取得不重复值的方式来实现去重,这让编程者思维局限在数组里。其实js世界为我们提供了现成的去重偏方——对象{},因为对象的键名是唯一的,我们利用这一特性,把值作为对象的键名就可以实现去重,于是:

var uniq2=function(arr){
    var i,temp=[],
        key,newArr=[];

    for(i=0;i<arr.length;i+=1){//遍历数组,将值作为键名放入对象中
        temp[arr[i]] = (temp[arr[i]]+1)||1;//对象值随便赋,用作重复次数的统计是个不错的选择
    }

    for(key in temp){//把生成的临时对象转回数组
        newArr.push(key);
    }

    return newArr;
};

逻辑清晰,效果很好。由于是直接对对象键名的覆盖,无需比对重复值,循环体的运算复杂度大大减少,这在做大量数据操作时对性能的提升会很明显,因为无论如何仅仅是对数组的一次遍历而已。我们写个简单的测试得到如下结果:

测试结果1

优势明显!但是带来一个新问题,我们遍历结果发现所有的值都变成了字符串!还有,如果是对象集合的去重呢?我们知道对象的键名是字符串,不能直接用对象字面量,真是没有银弹!怎么办?我们依旧沿袭“偷懒的作风”,用js给我们提供的现成方法JSON.stringify()把对象转成字符串,在去重完成后用JSON.parse()方法转回对象字面量……好吧,这太容易了,所以,我再偷下懒,完整的实现代码就由各位自由发挥吧,很容易不是吗。

据说写个ES6代码在用Babel转换下不就好了……然而用户需求是无止境的依然有人不放弃对<ie8的支持。并且我发现第二种方法即使加上JSON的解析,在性能上依然优于[...new Set(arr)]

测试结果2

可能这点数据量还不足以体现这种方法的巨大优势,我们加点料再测一次:

测试结果3

完胜啊!

关于去重还有很多话题可以展开,比如算法、对结果排序的影响等,但归根结底还是性能优化、高效处理。这是个很有趣味的主题!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 本文为阮一峰大神的《ECMAScript 6 入门》的个人版提纯! babel babel负责将JS高级语法转义,...
    Devildi已被占用阅读 6,096评论 0 4
  • 下面不属于ECMAScript规范的范围的是:( )A、 数据类型B、 语法C、 DOM事件D、 内置对象和函数的...
    亓凡阅读 8,113评论 3 9
  • 骤雨初歇,秋凉西风疏桐叶。 万家灯灭,玉簟孤枕夜。 高位维艰,何日夫郎卸。 烛光曳,锦书将写,落笔心怯怯。
    小木山庄的溜溜阅读 2,498评论 2 8
  • 目录[https://www.jianshu.com/p/276212c4ad9b] 前篇[https://www...
    北雫阅读 3,685评论 0 0
  • 今天分享的主题是“踢猫效应”,想必大家从字面的意思就会有点疑惑吧?为什么是踢猫了?不是踢狗,或者是狮子?大家可以脑...
    SeeOne阅读 1,553评论 0 0

友情链接更多精彩内容