javascript数组去掉重复


Posted in Javascript onMay 12, 2011

总得来说面试的过程还是收获了不少,主要是认清自己的差距到底有多大,知识面到底有多窄,适当打击一下自信心还是有必要的。在这里做一次全面的总结,关于javascript的数组去重问题。

考虑一个问题由简到繁相对容易接受一点,首先假设要去重的数组是比较简单的,例如:

var arr=[1,2,2,3,'5',6,5,'',' ']

这个数组只包含了数字,字符串两种类型。我们给数组原型上面添加去重的方法distinct,用第一种很容易想到的方法来实现,当然也是很笨很直接的,把这个数组复制一份然后循环两个数组,对比当前值与后面所有的值是否相等,如果与后面所有值都不等则把该值存到新数组里,如此最后再返回该新数组。方法如下:
//第一种方法 
Array.prototype.distinct=function(){ 
var clone,newArr=[],n=0; 
if(this.length<2)return; 
clone=this; 
for(var i=0,len=this.length;i<len;i++){ 
for(var j=i+1,len2=clone.length;j<len2;j++){ 
if(this[i]!==clone[j]){ 
n++; 
} 
} 
if(n==(len-i-1)){ 
newArr.push(this[i]) 
} 
n=0; 
} 
return newArr; 
} 
console.log([1,2,2,3,'5',6,5,'',' '].distinct()); 
/*获得被check的radio的值*/ 
function GetRadioValue(RadioName){ 
var obj; 
obj=document.getElementsByName(RadioName); 
if(obj!=null){ 
var i; 
for(i=0;i<obj.length;i++){ 
if(obj[i].checked){ 
return obj[i].value; 
} 
} 
} 
return null; 
} /*设置被选中属性*/ 
function SetRadioCheck(RadioName,i){ 
var obj; 
obj=document.getElementsByName(RadioName); 
obj[i].setAttribute("checked","checked"); 
}

基本可以满足我们的需求,对这样简单的类型比较确实不用费太多的脑经,但如果数组很长呢?如此遍历数组,数组长度为n,那么时间复杂度为n*n。显然该方法性能还有待提升。接下来是第二种方法,用到数组排序,在排序的过程去除重复的值。
//第二种方法 
Array.prototype.distinct=function(){ 
var newArr=this.concat().sort(),self=this; 
newArr.sort(function(a,b){ 
var n; 
if(a===b){ 
n=self.indexOf(a); 
self.splice(n,1); 
} 
}); 
return self; 
} 
console.log([1,2,2,3,'5',6,5,6,6,15,5,'5',5,'',' '].distinct());

这样代码看起来似乎短了很多,甚至连一个for循环都没有,但是sort得效率也高不到哪里去。再来看看第三种实现方法,用到的对象属性不会重名的原理
//第三种方法 
Array.prototype.distinct=function(){ 
var newArr=[],obj={}; 
for(var i=0,len=this.length;i<len;i++){ 
if(!obj[this[i]]){ 
newArr.push(this[i]); 
obj[this[i]]='new'; 
} 
} 
return newArr; 
} 
console.log([1,2,2,3,'5',6,5,6,6,15,5,'5',5,'',' '].distinct());

第三种方法运行看下结果,会发现跟上面的方法实现的结果不一致,细看原来它把数字5和字符串5当成重复的值给去掉了。看来类型必须保存起来然后再判断是否相等,这样便有了下面的第三种方法的补充版
//第三种方法补充版 
Array.prototype.distinct=function(){ 
var newArr=[],obj={}; 
for(var i=0,len=this.length;i<len;i++){ 
if(!obj[typeof(this[i])+this[i]]){ 
newArr.push(this[i]); 
obj[typeof(this[i])+this[i]]='new'; 
} 
} 
return newArr; 
}

上面举的例子是很简单的类型,我们拿更复杂的类型来测试一下
console.log([1,null,2,{a:'vc'},{},'5',6,5,6,{a:'vv'},15,5,'5',5,'',' ',[1],[1],[1,2],,].distinct());

发现{a:'vc'},{},{a:'vv'}这些不同的对象还是会被剔除掉,如果数组里面有对象则要继续遍历对象里面的属性和值,继续第三种方法的加强
//第三种方法加强版 
Array.prototype.distinct=function(){ 
var sameObj=function(a,b){ 
var tag = true; 
if(!a||!b)return false; 
for(var x in a){ 
if(!b[x]) 
return false; 
if(typeof(a[x])==='object'){ 
tag=sameObj(a[x],b[x]); 
}else{ 
if(a[x]!==b[x]) 
return false; 
} 
} 
return tag; 
} 
var newArr=[],obj={}; 
for(var i=0,len=this.length;i<len;i++){ 
if(!sameObj(obj[typeof(this[i])+this[i]],this[i])){ 
newArr.push(this[i]); 
obj[typeof(this[i])+this[i]]=this[i]; 
} 
} 
return newArr; 
}

用上面的例子测试发现基本木有问题,当然测试还可以更加变态更加纠缠,这里就不去深究了,目前来看此篇方法在网上属于比较齐全的,如果有更好更完善的方法请不吝赐教。
Javascript 相关文章推荐
Jquery 滑入滑出效果实现代码
Mar 27 Javascript
jquery星级插件、支持页面中多次使用
Mar 25 Javascript
jQuery extend 的简单实例
Sep 18 Javascript
Chrome下ifame父窗口调用子窗口的问题示例探讨
Mar 17 Javascript
indexOf 和 lastIndexOf 使用示例介绍
Sep 02 Javascript
5种处理js跨域问题方法汇总
Dec 04 Javascript
jQuery 常用代码集锦(必看篇)
May 16 Javascript
原生js实现可爱糖果数字时间特效
Dec 30 Javascript
Vue2.0实现1.0的搜索过滤器功能实例代码
Mar 20 Javascript
vue 解决addRoutes动态添加路由后刷新失效问题
Jul 02 Javascript
jQuery事件委托代码实践详解
Jun 21 jQuery
vue项目中锚点定位替代方式
Nov 13 Javascript
javascript 弹出层组件(升级版)
May 12 #Javascript
ExtJS4 组件化编程,动态加载,面向对象,Direct
May 12 #Javascript
关于js获取radio和select的属性并控制的代码
May 12 #Javascript
js 第二代身份证号码的验证机制代码
May 12 #Javascript
基于JQuery的动态删除Table表格的行和列的代码
May 12 #Javascript
五个jQuery图片画廊插件 推荐
May 12 #Javascript
JavaScript 继承使用分析
May 12 #Javascript
You might like
怎样在php中使用PDF文档功能
2006/10/09 PHP
收集的PHP中与数组相关的函数
2007/03/22 PHP
比较全的PHP 会话(session 时间设定)使用入门代码
2008/06/05 PHP
PHP文件读写操作之文件写入代码
2011/01/13 PHP
PHP实现递归无限级分类
2015/10/22 PHP
SAE实时日志接口SDK用法示例
2016/10/09 PHP
php自定义函数实现统计中文字符串长度的方法小结
2017/04/15 PHP
URL地址中的#符号使用说明
2011/02/12 Javascript
纯JS实现根据CSS的class选择DOM
2014/03/22 Javascript
Js可拖拽放大的层拖动特效实现方法
2015/02/25 Javascript
快速解决jquery.touchSwipe左右滑动和垂直滚动条冲突
2016/04/15 Javascript
React创建组件的三种方式及其区别
2017/01/12 Javascript
a标签置灰不可点击的实现方法
2017/02/06 Javascript
node.js(express)中使用Jcrop进行图片剪切上传功能
2017/04/21 Javascript
深入理解vuex2.0 之 modules
2017/11/20 Javascript
vue项目中引入Sass实例方法
2019/08/27 Javascript
原生js+canvas实现贪吃蛇效果
2020/08/02 Javascript
vue自定义指令限制输入框输入值的步骤与完整代码
2020/08/30 Javascript
[02:56]《DAC最前线》之国外战队抵达上海备战亚洲邀请赛
2015/01/28 DOTA
[57:53]DOTA2上海特级锦标赛主赛事日 - 2 败者组第二轮#3OG VS VP
2016/03/03 DOTA
python实现的系统实用log类实例
2015/06/30 Python
Python while 循环使用的简单实例
2016/06/08 Python
解决Ubuntu pip 安装 mysql-python包出错的问题
2018/06/11 Python
详解Django 中是否使用时区的区别
2018/06/14 Python
python基于itchat模块实现微信防撤回
2019/04/29 Python
设计师家具购买和委托在线市场:Viyet
2016/11/16 全球购物
项目经理的岗位职责
2013/11/23 职场文书
办公室打字员岗位职责
2014/04/16 职场文书
卫校毕业生自我鉴定
2014/09/28 职场文书
2014年党员教师自我剖析材料
2014/09/30 职场文书
干部作风建设个人剖析材料
2014/10/11 职场文书
python中pandas.read_csv()函数的深入讲解
2021/03/29 Python
详解Laravel制作API接口
2021/05/31 PHP
SpringBoot集成MongoDB实现文件上传的步骤
2022/04/18 MongoDB
Redis特殊数据类型Geospatial地理空间
2022/06/01 Redis