详解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 相关文章推荐
javascript新手语法小结
Jun 15 Javascript
JavaScript打开word文档的实现代码(c#)
Apr 16 Javascript
javascript setTimeout和setInterval计时的区别详解
Jun 21 Javascript
ie 7/8不支持trim的属性的解决方案
May 23 Javascript
JavaScript判断DIV内容是否为空的方法
Jan 29 Javascript
javascript简单实现等比例缩小图片的方法
Jul 27 Javascript
Vuejs第一篇之入门教程详解(单向绑定、双向绑定、列表渲染、响应函数)
Sep 09 Javascript
Vue学习笔记进阶篇之过渡状态详解
Jul 14 Javascript
webpack vue 项目打包生成的文件,资源文件报404问题的修复方法(总结篇)
Jan 09 Javascript
js中int和string数据类型互相转化实例
Jan 16 Javascript
layui 阻止图片上传的实例(before方法)
Sep 26 Javascript
详解webpack-dev-middleware 源码解读
Mar 23 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
php木马攻击防御之道
2008/03/24 PHP
Yii操作数据库的3种方法
2014/03/11 PHP
一漂亮的PHP图片验证码实例
2014/03/21 PHP
PHP获取当前页面URL函数实例
2014/10/22 PHP
php+ajax 文件上传代码实例
2019/03/18 PHP
在laravel中实现将查询的对象转换为多维数组的函数
2019/10/21 PHP
JavaScript中实现块作用域的方法
2010/04/01 Javascript
javascript 基础篇4 window对象,DOM
2012/03/14 Javascript
jquery控制左右箭头滚动图片列表的实例
2013/05/20 Javascript
使用Meteor配合Node.js编写实时聊天应用的范例
2015/06/23 Javascript
Jquery跨域获得Json的简单实例
2016/05/18 Javascript
详解AngularJS 路由 resolve用法
2017/04/24 Javascript
关于js中的鼠标事件总结
2017/07/11 Javascript
SpringMVC简单整合Angular2的示例
2017/07/31 Javascript
webpack 4.0.0-beta.0版本新特性介绍
2018/02/10 Javascript
Vue项目中设置背景图片方法
2018/02/21 Javascript
优雅地使用loading(推荐)
2019/04/20 Javascript
HTML+JavaScript实现扫雷小游戏
2019/09/30 Javascript
搭建Vue从Vue-cli到router路由护卫的实现
2019/11/14 Javascript
Python模块学习 filecmp 文件比较
2012/08/27 Python
PyMongo安装使用笔记
2015/04/27 Python
python实现判断数组是否包含指定元素的方法
2015/07/15 Python
Python实现随机生成有效手机号码及身份证功能示例
2017/06/05 Python
python使用os.listdir和os.walk获得文件的路径的方法
2017/12/16 Python
Python实现画图软件功能方法详解
2020/07/28 Python
只要五步 就可以用HTML5/CSS3快速制作便签贴特效(图)
2012/06/04 HTML / CSS
卡塔尔航空官方网站:Qatar Airways
2017/02/08 全球购物
类成员函数的重载、覆盖和隐藏区别
2016/01/27 面试题
什么是测试驱动开发(TDD)
2012/02/15 面试题
资深财务管理人员自我评价
2013/09/22 职场文书
愚人节活动策划方案
2014/03/11 职场文书
市场部经理岗位职责
2014/04/10 职场文书
校园文明标语
2014/06/13 职场文书
党的群众路线教育实践活动领导班子整改措施
2014/10/28 职场文书
员工工作能力评语
2014/12/31 职场文书
Python写情书? 10行代码展示如何把情书写在她的照片里
2022/04/21 Python