详解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 相关文章推荐
分享十五个最佳jQuery 幻灯插件和教程
Mar 27 Javascript
纯JS实现动态时间显示代码
Feb 08 Javascript
JavaScript中的原型链prototype介绍
Dec 30 Javascript
举例详解Python中smtplib模块处理电子邮件的使用
Jun 24 Javascript
JavaScript数据类型学习笔记
Jan 25 Javascript
angular-ui-sortable实现可拖拽排序列表
Dec 28 Javascript
jQuery之动画ajax事件(实例讲解)
Jul 18 jQuery
js Dom实现换肤效果
Oct 21 Javascript
微信小程序wx.getImageInfo()如何获取图片信息
Jan 26 Javascript
解决node-sass偶尔安装失败的方法小结
Dec 05 Javascript
Vue 自定义标签的src属性不能使用相对路径的解决
Sep 17 Javascript
JS原形与原型链深入详解
May 09 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将某个目录下面的所有文件罗列出来的方法详解
2013/06/21 PHP
Ajax+PHP实现的模拟进度条功能示例
2019/02/11 PHP
代码精简的可以实现元素圆角的js函数
2007/07/21 Javascript
Jquery ajax不能解析json对象,报Invalid JSON错误的原因和解决方法
2010/03/27 Javascript
JavaScript的单例模式 (singleton in Javascript)
2010/06/11 Javascript
查看图片(前进后退)功能实现js代码
2013/04/24 Javascript
jquery select多选框的左右移动 具体实现代码
2013/07/03 Javascript
javascript同页面多次调用弹出层具体实例代码
2013/08/16 Javascript
JavaScript使用focus()设置焦点失败的解决方法
2014/09/03 Javascript
jquery 实现两Select 标签项互调示例代码
2014/09/25 Javascript
JavaScript的代码编写格式规范指南
2015/12/07 Javascript
ES6中非常实用的新特性介绍
2016/03/10 Javascript
JS中substring与substr的用法
2016/11/16 Javascript
原生node.js案例--前后台交互
2017/02/20 Javascript
vue的全局变量和全局拦截请求器的示例代码
2018/09/13 Javascript
详解js常用分割取字符串的方法
2019/05/15 Javascript
layui文件上传控件带更改后数据传值的方法
2019/09/23 Javascript
vue实现表单录入小案例
2019/09/27 Javascript
vue-cli在 history模式下的配置详解
2019/11/26 Javascript
JavaScript Event Loop相关原理解析
2020/06/10 Javascript
详解python发送各类邮件的主要方法
2016/12/22 Python
django中send_mail功能实现详解
2018/02/06 Python
tensorflow实现KNN识别MNIST
2018/03/12 Python
解决pycharm的Python console不能调试当前程序的问题
2019/01/20 Python
python 实现一次性在文件中写入多行的方法
2019/01/28 Python
Pyqt QImage 与 np array 转换方法
2019/06/27 Python
使用已经得到的keras模型识别自己手写的数字方式
2020/06/29 Python
微信端html5页面调用分享接口示例
2018/03/14 HTML / CSS
香港太阳眼镜网上商店:SmartBuyGlasses香港
2016/07/22 全球购物
工厂仓管员岗位职责
2014/01/01 职场文书
幼儿园老师寄语
2014/04/03 职场文书
教师竞聘演讲稿
2014/05/16 职场文书
旅游与环境专业求职信
2014/06/05 职场文书
整改通知书格式
2015/04/22 职场文书
2019年国庆祝福语(70句)
2019/09/19 职场文书
2019年励志签名:致拼搏路上的自己
2019/10/11 职场文书