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 相关文章推荐
关于javascript中的typeof和instanceof介绍
Dec 04 Javascript
window.navigate 与 window.location.href 的使用区别介绍
Sep 21 Javascript
将form表单中的元素转换成对象的方法适用表单提交
May 02 Javascript
js时间控件只显示年月
Jan 08 Javascript
js实现文字向上轮播功能
Jan 13 Javascript
基于JS实现bookstore静态页面的实例代码
Feb 22 Javascript
详解JS异步加载的三种方式
Mar 07 Javascript
JavaScript伪数组用法实例分析
Dec 22 Javascript
layui select动态添加option的实例
Mar 07 Javascript
Vue 实时监听窗口变化 windowresize的两种方法
Nov 06 Javascript
vue实现扫码功能
Jan 17 Javascript
js 数组 fill() 填充方法
Nov 02 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取整数函数常用的四种方法小结
2012/07/05 PHP
php实现批量压缩图片文件大小的脚本
2014/07/04 PHP
万能的php分页类
2017/07/06 PHP
PHP获取本周所有日期或者最近七天所有日期的方法
2018/06/20 PHP
PHP使用gearman进行异步的邮件或短信发送操作详解
2020/02/27 PHP
文字不间断滚动(上下左右)实例代码
2013/04/21 Javascript
jquery实现兼容浏览器的图片上传本地预览功能
2013/10/14 Javascript
js获取鼠标点击的位置实现思路及代码
2014/05/09 Javascript
jQuery实现的图片分组切换焦点图插件
2015/01/06 Javascript
jQuery Mobile 触摸事件实例
2016/06/04 Javascript
JS弹出新窗口被拦截的解决方法
2016/08/09 Javascript
Windows环境下npm install 报错: operation not permitted, rename的解决方法
2016/09/26 Javascript
bootstrap select下拉搜索插件使用方法详解
2017/11/23 Javascript
electron demo项目npm install安装失败的解决方法
2018/02/06 Javascript
vue全局组件与局部组件使用方法详解
2018/03/29 Javascript
提升node.js中使用redis的性能遇到的问题及解决方法
2018/10/30 Javascript
vue ssr 实现方式(学习笔记)
2019/01/18 Javascript
Javascript摸拟自由落体与上抛运动原理与实现方法详解
2020/04/08 Javascript
Vue项目前后端联调(使用proxyTable实现跨域方式)
2020/07/18 Javascript
微信小程序弹窗禁止页面滚动的实现代码
2020/12/30 Javascript
Python基础教程之浅拷贝和深拷贝实例详解
2017/07/15 Python
树莓派4B+opencv4+python 打开摄像头的实现方法
2019/10/18 Python
Python要如何实现列表排序的几种方法
2020/02/21 Python
详解Ubuntu环境下部署Django+uwsgi+nginx总结
2020/04/02 Python
Python实现常见的几种加密算法(MD5,SHA-1,HMAC,DES/AES,RSA和ECC)
2020/05/09 Python
django 模型字段设置默认值代码
2020/07/15 Python
Python 操作 MySQL数据库
2020/09/18 Python
python 装饰器的基本使用
2021/01/13 Python
社团招新策划书
2014/02/04 职场文书
兴趣小组活动总结
2014/05/05 职场文书
2014年企业党支部工作总结
2014/12/04 职场文书
2015年学生会个人工作总结
2015/04/09 职场文书
初中政治教学工作总结
2015/08/13 职场文书
导游词之上海豫园
2019/10/24 职场文书
python基础之文件处理知识总结
2021/05/23 Python
用Python爬取各大高校并可视化帮弟弟选大学,弟弟直呼牛X
2021/06/11 Python