详解javascript数组去重问题


Posted in Javascript onNovember 06, 2015

首先,我想到的是另建一个结果数组,用来存储原始数组中不重复的数据。遍历原始数组依次跟结果数组中的元素进行比较,检测是否重复。于是乎,我写出了如下代码A

Array.prototype.clearRepetitionA = function(){
   var result = [];
   var isRepetition;
   for(var i=0; i<this.length; i++){
     isRepetition = false;
     for(var j=0; j<result.length; j++){
       if(this[i] === result[j]){
         isRepetition = true;
         break;
       }
     }
     if(!isRepetition){
       result.push(this[i]);
     }
   }
   return result;
 }

写完之后,忽然想起来前几天刚看的ECMAScript 5中的数组方法indexOf 可以检索数组元素。于是我又使用indexOf 方法替代了第二层循环,写出了如下代码B

Array.prototype.clearRepetitionB = function(){
   var result = [];
   for(var i=0; i<this.length; i++){
     if(result.indexOf(this[i]) == -1){
       result.push(this[i]);
     }
   }
   return result;
 }

代码一下子从17行变成了9行了,简洁多了。高三数学大题解法一般都不止一种的啊,然后我就继续再想其他方法了。indexOf 方法的意思是搜索整个数组中具有给定值的元素,返回找到的第一个元素的索引,没有找到就返回 -1 ,第一个参数就是要搜索的值,第二个参数可选:它指定数组中的一个索引,从那里开始搜索,如果省略这个参数,则从头搜索。思维一发散,想到了前面方法都是检测值是否重复的,现在有了indexOf 方法不就可以根据检测到的每个元素的第一次出现时的索引和这个元素自身的索引值比较相等来判断是否重复嘛。所以,我又写出了代码C:

Array.prototype.clearRepetitionC = function(){
   var result = [this[0]];
   for(var i=1; i<this.length; i++){
     if(this.indexOf(this[i]) == i){
       result.push(this[i]);
     }
   }
   return result;
 }

写完这个,又继续想了想,实在是想不出其他方法了,这三个方法都是很基础的方法。于是,我就去对照答案,检验自己了。一看答案,发现自己还是真实太弱了,简单的问题还是有些奇思妙想的。下面不是自己想的了,就不再说太多我的心路历程了。废话不多说,直接上经典的答案+解析了。
首先,先说一个算法中经常说的以空间换时间的解法,保持队形,我们就叫它代码D吧:

Array.prototype.clearRepetitionD = function(){
   var result = [];
   var obj = {};
   var key,type;
   for(var i=0; i<this.length; i++){
     key = this[i];
     type = typeof key;
     if(!obj[key]){
       obj[key] = [type];
       result.push(key);
     }else if(obj[key].indexOf(type)){
       obj[key].push(type);
       result.push(key);
     }
   }
   return result;
 }

这个方法中在遍历原始数组时用一个对象 obj 的属性来保存原始数组中元素的值。同时这个属性的值是一个数组,用来存储这个属性的类型,这一点可以把原始数组中类似数字1元素和字符串‘1'的元素区分开。这个方法通过额外构建一个对象的方式降低了上面三种方法中indexOf方法所花费的时间,可以说较为高效吧。
如果你已经满足于上面所说的以空间换时间的高效方法而不继续看下去的话,那就大错特错了,好戏总在后头嘛。现在好戏开场,毫无疑问,就是代码E了:

Array.prototype.clearRepetitionE = function(){
   var result = [];
   for(var i=0; i<this.length; i++){
     for(var j=i+1; j<this.length; j++){
       if(this[i] === this[j]){
         j = ++i;
       }
     }
     result.push(this[i]);
   }
   return result;
 }

代码D以空间换时间,感觉也就一般般。那么代码E呢?这代码是错误的吧,这个真的能去重吗?是的,起初我都没看懂这代码,看了解析后又看了一遍之后才明白过来。那么,没看懂的看官也要认真的看解析了:第一层从前往后遍历原始数组,第二层循环是检测每个元素是否跟它之后的元素重复,如果它之后有重复元素则跳过它;如果这个元素之后所有元素都跟他不重复了,则把它添加到结果数组中。这个方法实现思路就是:获取无重复的最右一值添加到结果数组中,这个跟第一种方法相比也优化了第二层的循环,效率要比它高,不过这个方法的结果数组中元素的顺序跟原始数组中元素的顺序不一样了。

看完了代码E解析的你是不是已经伸出了大拇指、投放出了敬佩的目光呢?(这些鲜花和荣誉别给我,应该给写这个方法的大神去)。下面再说最后一个方法:那就是先排序,再去重。老规矩,它叫代码F

Array.prototype.clearRepetitionF = function(){
   this.sort();
   var result = [this[0]];
   for(var i=1; i<this.length; i++){
     if(this[i] !== result[result.length-1]){
       result.push(this[i]);
     }
   }
   return result;
 }

这个先用数组的排序方法sort进行数组元素排序,然后再进行去重工作。

以上就是对javascript数组去重问题的一步步研究,不断改进代码,总共分享了六段代码,希望大家认真学习,能够有所收获。

Javascript 相关文章推荐
js获得鼠标的坐标值的方法
Mar 13 Javascript
JavaScript中消除闭包的一般方法介绍
Mar 16 Javascript
JavaScript encodeURI 和encodeURIComponent
Dec 04 Javascript
Javascript实现信息滚动效果
May 18 Javascript
vue轮播图插件vue-awesome-swiper
Nov 27 Javascript
修改UA在PC中访问只能在微信中打开的链接方法
Nov 27 Javascript
Angular5集成eventbus的示例代码
Jul 19 Javascript
angular将html代码输出为内容的实例
Sep 30 Javascript
vue-cli随机生成port源码的方法
Sep 02 Javascript
使用JS location实现搜索框历史记录功能
Dec 23 Javascript
React + Threejs + Swiper 实现全景图效果的完整代码
Jun 28 Javascript
JS实现简单的九宫格抽奖
Jun 28 Javascript
基于JavaScript实现仿京东图片轮播效果
Nov 06 #Javascript
实现非常简单的js双向数据绑定
Nov 06 #Javascript
浅析javascript中的事件代理
Nov 06 #Javascript
详解javascript中的事件处理
Nov 06 #Javascript
jQuery插件实现静态HTML验证码校验
Nov 06 #Javascript
jQuery Real Person验证码插件防止表单自动提交
Nov 06 #Javascript
jQuery实现非常实用漂亮的select下拉菜单选择效果
Nov 06 #Javascript
You might like
简单的页面缓冲技术
2006/10/09 PHP
PHP 八种基本的数据类型小结
2011/06/01 PHP
php实现可逆加密的方法
2015/08/11 PHP
PHP实现将几张照片拼接到一起的合成图片功能【便于整体打印输出】
2017/11/14 PHP
jQuery对象和DOM对象相互转化
2009/04/24 Javascript
jQuery实现3D文字特效的方法
2015/03/10 Javascript
浅谈JavaScript超时调用和间歇调用
2015/08/30 Javascript
jqGrid中文文档之选项设置
2015/12/02 Javascript
深入理解MVC中的时间js格式化
2016/05/19 Javascript
AngularJS实现分页显示数据库信息
2016/07/01 Javascript
vueJs实现DOM加载完之后自动下拉到底部的实例代码
2018/08/31 Javascript
详解关于Vue2.0路由开启keep-alive时需要注意的地方
2018/09/18 Javascript
mockjs+vue页面直接展示数据的方法
2018/12/19 Javascript
微信小程序五子棋游戏AI实现方法【附demo源码下载】
2019/02/20 Javascript
浅谈layui 绑定form submit提交表单的注意事项
2019/10/25 Javascript
[37:37]DAC2018 4.4 淘汰赛 Optic vs Mineski 第二场
2018/04/05 DOTA
[40:53]完美世界DOTA2联赛PWL S3 Magma vs DLG 第二场 12.18
2020/12/20 DOTA
python cookielib 登录人人网的实现代码
2012/12/19 Python
用Python的pandas框架操作Excel文件中的数据教程
2015/03/31 Python
用virtualenv建立多个Python独立虚拟开发环境
2017/07/06 Python
python3 读写文件换行符的方法
2018/04/09 Python
python 执行shell命令并将结果保存的实例
2018/05/11 Python
利用python库在局域网内传输文件的方法
2018/06/04 Python
python读取xlsx的方法
2018/12/25 Python
python 模拟登陆github的示例
2020/12/04 Python
Python日志打印里logging.getLogger源码分析详解
2021/01/17 Python
详解如何获取localStorage最大存储大小的方法
2020/05/21 HTML / CSS
英国Iceland杂货店:网上食品购物
2020/12/16 全球购物
艺术系应届生的自我评价
2013/10/19 职场文书
文秘自荐信
2013/10/20 职场文书
家具公司总经理岗位职责
2014/07/08 职场文书
团队拓展活动方案
2014/08/28 职场文书
个人作风建设自查报告
2014/10/22 职场文书
青年教师个人总结
2015/02/11 职场文书
2015年父亲节寄语
2015/03/23 职场文书
高一作文之暖冬
2019/11/09 职场文书