详解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 相关文章推荐
filters.revealTrans.Transition使用方法小结
Aug 19 Javascript
jquery判断浏览器类型的代码
Nov 05 Javascript
javascript客户端遍历控件与获取父容器对象示例代码
Jan 06 Javascript
使用JQ来编写最基本的淡入淡出效果附演示动画
Oct 31 Javascript
快速学习jQuery插件 Cookie插件使用方法
Dec 01 Javascript
用Vue.js实现监听属性的变化
Nov 17 Javascript
基于JS实现弹出一个隐藏的div窗口body页面变成灰色并且不可被编辑
Dec 14 Javascript
JS实现改变HTML上文字颜色和内容的方法
Dec 30 Javascript
npm国内镜像 安装失败的几种解决方案
Jun 04 Javascript
ES6之模版字符串的具体使用
May 17 Javascript
JQuery实现简单的复选框树形结构图示例【附源码下载】
Jul 16 jQuery
JavaScript实现复选框全选功能
Apr 11 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
smarty模板引擎之内建函数用法
2015/03/30 PHP
Yii基于数组和对象的Model查询技巧实例详解
2015/12/28 PHP
yii2中添加验证码的实现方法
2016/01/09 PHP
php注册登录系统简化版
2020/12/28 PHP
PHP中命名空间的使用例子
2019/03/22 PHP
phpmyadmin在宝塔面板里进不去的解决方案
2020/07/06 PHP
JavaScript实现自己的DOM选择器原理及代码
2013/03/04 Javascript
JavaScript获取多个数组的交集简单实例
2013/11/11 Javascript
基于JS实现的倒计时程序实例
2015/07/24 Javascript
JavaScript动态创建form表单并提交的实现方法
2015/12/10 Javascript
简单了解JavaScript操作XPath的一些基本方法
2016/06/03 Javascript
jquery实现全选、全不选以及单选功能
2017/03/23 jQuery
AngularJS1.X学习笔记2-数据绑定详解
2017/04/01 Javascript
jQuery遮罩层实例讲解
2017/05/11 jQuery
vue2.0 常用的 UI 库实例讲解
2017/12/12 Javascript
在 React、Vue项目中使用SVG的方法
2018/02/09 Javascript
node.js自动上传ftp的脚本分享
2018/06/16 Javascript
vue.js动画中的js钩子函数的实现
2018/07/06 Javascript
小程序实现横向滑动日历效果
2019/10/21 Javascript
JS实现简单省市二级联动
2019/11/27 Javascript
js验证密码强度解析
2020/03/18 Javascript
JS this关键字在ajax中使用出现问题解决方案
2020/07/17 Javascript
VSCode插件安装完成后的配置(常用配置)
2020/08/24 Javascript
JavaScript的一些小技巧分享
2021/01/06 Javascript
使用pdb模块调试Python程序实例
2015/06/02 Python
Python设置Socket代理及实现远程摄像头控制的例子
2015/11/13 Python
Python类的继承用法示例
2019/01/31 Python
python创建文本文件的简单方法
2020/08/30 Python
html5清空画布方法(三种)
2017/10/16 HTML / CSS
h5页面背景图很长要有滚动条滑动效果的实现
2021/01/27 HTML / CSS
Lookfantastic瑞典:英国知名美妆购物网站
2018/04/06 全球购物
学校师德师风整改措施
2014/10/27 职场文书
2016社区平安家庭事迹材料
2016/02/26 职场文书
剑指Offer之Java算法习题精讲二叉树的构造和遍历
2022/03/21 Java/Android
vue @ ~ 相对路径 路径别名设置方式
2022/06/05 Vue.js
SQL Server2019安装的详细步骤实战记录(亲测可用)
2022/06/10 SQL Server