详解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实现多级下拉菜单的实例代码
Oct 02 Javascript
JavaScript实现大数的运算
Nov 24 Javascript
jquery增加和删除元素的方法
Jan 14 Javascript
JavaScript的Polymer框架中dom-repeat与VM的相关操作
Jul 29 Javascript
JS跨域请求外部服务器的资源
Feb 06 Javascript
JSONP跨域请求
Mar 02 Javascript
jQuery length 和 size()区别总结
Apr 26 jQuery
layer弹出层父子页面事件相互调用方法
Aug 17 Javascript
浅谈vue 单文件探索
Sep 05 Javascript
electron实现静默打印的示例代码
Aug 12 Javascript
vue项目实现图片上传功能
Dec 23 Javascript
JS实现页面数据懒加载
Feb 13 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 smarty的预保留变量总结
2008/12/04 PHP
PHP判断远程url是否有效的几种方法小结
2011/10/08 PHP
php 阴历-农历-转换类代码
2012/01/16 PHP
PHP URL参数获取方式的四种例子
2014/02/28 PHP
Laravel框架验证码类用法实例分析
2019/09/11 PHP
parentElement,srcElement的使用小结
2014/01/13 Javascript
javascipt:filter过滤介绍及使用
2014/09/10 Javascript
js判断浏览器版本以及浏览器内核的方法
2015/01/20 Javascript
JavaScript中string对象
2015/06/12 Javascript
jquery+CSS3实现淘宝移动网页菜单效果
2015/08/31 Javascript
jQuery遮罩层效果实例分析
2016/01/14 Javascript
详解javascript传统方法实现异步校验
2016/01/22 Javascript
jQuery插件FusionCharts绘制2D环饼图效果示例【附demo源码】
2017/04/10 jQuery
JavaScript 中使用 Generator的方法
2017/12/29 Javascript
AjaxUpLoad.js实现文件上传功能
2018/03/02 Javascript
封装Vue Element的table表格组件的示例详解
2020/08/19 Javascript
[52:03]Secret vs VG 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/20 DOTA
python实现将汉字转换成汉语拼音的库
2015/05/05 Python
python中nan与inf转为特定数字方法示例
2017/05/11 Python
Python使用正则表达式过滤或替换HTML标签的方法详解
2017/09/25 Python
Python数据处理numpy.median的实例讲解
2018/04/02 Python
Python引用计数操作示例
2018/08/23 Python
python树莓派红外反射传感器
2019/01/21 Python
python 计算平均平方误差(MSE)的实例
2019/06/29 Python
利用Python库Scapy解析pcap文件的方法
2019/07/23 Python
Python任务调度利器之APScheduler详解
2020/04/02 Python
Python3爬虫中关于Ajax分析方法的总结
2020/07/10 Python
美国高级工作服品牌:Carhartt
2018/01/25 全球购物
Swanson中国官网:美国斯旺森健康产品公司
2021/03/01 全球购物
2014年职称评定工作总结
2014/11/26 职场文书
物流业务员岗位职责
2015/04/03 职场文书
校园音乐节目广播稿
2015/08/19 职场文书
2016应届毕业生就业指导课心得体会
2016/01/15 职场文书
postgresql使用filter进行多维度聚合的解决方法
2021/07/16 PostgreSQL
PO模式在selenium自动化测试框架的优势
2022/03/20 Python
git stash(储藏)的用法总结
2022/06/25 Servers