关于js数组去重的问题小结


Posted in Javascript onJanuary 24, 2014

1.根据js对象中key不重复的原则,构思出数组去重的方法,按照最常规的思维如下:

function distinctArray(arr){
var obj={},temp=[];
for(var i=0;i<arr.length;i++){
if(!obj[arr[i]]){
temp.push(arr[i]);
obj[arr[i]] =true;
}
}
return temp;
   }
   var testarr=[1,2,3,2];
   console.log(distinctArray(testarr));// [1,2,3]

看起来还不错的样子哦,但是如果变成一下情况:
var testarr1=[1,2,3,"2"];
console.log(distinctArray(testarr));// [1,2,3]
竟然还是一样的结果,这就并非我们想要的了,我们需要的结果应该是[1,2,3,"2"].即去重的过程中需要保证类型的完整性。

针对以上情况,我们对上述方法进行改进:

function distinctArrayImprove(arr){
var obj={},temp=[];
for(var i=0;i<arr.length;i++){
if(!obj[typeof (arr[i])+arr[i]]){
temp.push(arr[i]);
obj[typeof (arr[i])+arr[i]] =true;
}
}
return temp;
}

以上方法在向对象中放key的时候加了typeof的前缀,那么让我们看看效果吧。
var testarr1=[1,2,3,"2"];
console.log(distinctArray(testarr));// [1,2,3,"2"]
哎呦,不错哦!那么是不是这个函数就彻底ok呢,让我们再看一种情况!
var testarr1=[1,2,3,"2",{a:1},{b:1}];
console.log(distinctArray(testarr));// [1,2,3,"2",{a:1}]
竟然出现这个结果,怎么把{b:1}给莫名其妙的删掉了呢,去重的过程中如果出现误删除有用的数据可是很严重的问题,所以以上方法也不是perfect的一种,那就让我们接着往下看吧。

2.在1中我们的主要思想是利用js对象中key不重复的理念来指导我们的思维,但是最终没有解决所有的问题,那么接着我们可以考虑换一种思维模式来实现我们想要的功能。

用slice和splice方法来实现数组的去重,如下:

function distinctArray2(arr){
var temp=arr.slice(0);//数组复制一份到temp
for(var i=0;i<temp.length;i++){
for(j=i+1;j<temp.length;j++){
if(temp[j]==temp[i]){
temp.splice(j,1);//删除该元素
j--;
}
}
}
return temp;
}

测试:
var testarr1=[1,2,3,"2"];
console.log(distinctArray(testarr));// [1,2,3]
var testarr2=[1,2,2,{a:1},{a:1},{a:1,b:2},function(){alert("b");},function(){alert("b");}];
//[1,2,{a:1},{a:1},{a:1,b:2},function(){alert("b");},function(){alert("b");}]

测试结果仍然不能满足我们的需求,肿么办?经过我们队以上方法的研究,我们发现主要的问题出在比较两个对象相等的操作上,distinctArray2中利用”==“来比较,并不能区分大对象的内容是否相等,鉴于此种情况,我们另外写了一个方法:

function distinctArrayAll(arr){
var isEqual=function(obj1,obj2){
//两个对象地址相等,必相等
if(obj1===obj2){
return true;
}
if(typeof(obj1)==typeof(obj2)){
if(typeof(obj1)=="object"&&typeof(obj2)=="object"){
var pcount=0;
for(var p in obj1){
pcount++;
if(!isEqual(obj1[p],obj2[p])){
return false;
}
}
for(var p in obj2){
pcount--;
}
return pcount==0;
}else if(typeof(obj1)=="function"&&typeof(obj2)=="function"){
if(obj1.toString()!=obj2.toString()){
return false;
}
}else {
if(obj1!=obj2){
return false;
}
}
}else{
return false;
}
return true;
}
var temp=arr.slice(0);//数组复制一份到temp
for(var i=0;i<temp.length;i++){
for(j=i+1;j<temp.length;j++){
if(isEqual(temp[j],temp[i])){
temp.splice(j,1);//删除该元素
j--;
}
}
}
return temp;
}

测试:
var testArr3=[1,2,2,{a:1},{a:1},{a:1,b:2},function(){alert("b");},function(){alert("b");}];
console.log(distinctArrayAll(testArr3));
//结果 [1,2,{a:1},{a:1,b:2},function(){alert("b");}]

哎呀,终于顺利完成去重的任务了,至于每个方法的性能问题,我们留待下一次讨论!我们可以看出最后一种方法是万能去重法,可以针对复杂数组来去重,但是相应的执行开销也是相当大的,在实际的项目开发中有时我们需要的可能仅仅是纯数字或者纯字符串的去重,这就要求我们根据需求灵活选用相应的算法,不求太perfect,只求在满足需求的基础上使程序效率更高!

Javascript 相关文章推荐
各浏览器中querySelector和querySelectorAll的实现差异分析
May 23 Javascript
js网页实时倒计时精确到秒级
Feb 10 Javascript
在线所见即所得HTML编辑器的实现原理浅析
Apr 25 Javascript
jquery+ajax+text文本框实现智能提示完整实例
Jul 09 Javascript
一个简单的JavaScript Map实例(分享)
Aug 03 Javascript
JavaScript获取URL中参数querystring的方法详解
Oct 11 Javascript
Node.JS中事件轮询(Event Loop)的解析
Feb 25 Javascript
原生javascript上传图片带进度条【实例分享】
Apr 06 Javascript
利用js实现前后台传送Json的示例代码
Mar 29 Javascript
vue+iview/elementUi实现城市多选
Mar 28 Javascript
Vue事件修饰符native、self示例详解
Jul 09 Javascript
vue新建项目并配置标准路由过程解析
Dec 09 Javascript
js数组去重的常用方法总结
Jan 24 #Javascript
JQuery的$和其它JS发生冲突的快速解决方法
Jan 24 #Javascript
js判断60秒以及倒计时示例代码
Jan 24 #Javascript
innerText 使用示例
Jan 23 #Javascript
登陆成功后自动计算秒数执行跳转
Jan 23 #Javascript
检查输入的是否是数字使用keyCode配合onkeypress事件
Jan 23 #Javascript
html dom节点操作(获取/修改/添加或删除)
Jan 23 #Javascript
You might like
PHP实现通过正则表达式替换回调的内容标签
2015/06/15 PHP
PHP+MariaDB数据库操作基本技巧备忘总结
2018/05/21 PHP
php对象工厂类完整示例
2018/08/09 PHP
PHP array_reverse() 函数原理及实例解析
2020/07/14 PHP
JS使用oumousemove和oumouseout动态改变图片显示的方法
2015/03/31 Javascript
js实现刷新iframe的方法汇总
2015/04/27 Javascript
js实现仿Discuz文本框弹出层效果
2015/08/13 Javascript
jQuery实现点击小图显示大图代码分享
2015/08/25 Javascript
Angular.js中ng-if、ng-show和ng-hide的区别介绍
2017/01/20 Javascript
详解Vue路由开启keep-alive时的注意点
2017/06/20 Javascript
JavaScript反射与依赖注入实例详解
2018/05/29 Javascript
jQuery模拟html下拉多选框的原生实现方法示例
2019/05/30 jQuery
flexible.js实现移动端rem适配方案
2020/04/07 Javascript
vue项目使用$router.go(-1)返回时刷新原来的界面操作
2020/07/26 Javascript
[03:56]显微镜下的DOTA2第十一期——鬼畜的死亡先知播音员
2014/06/23 DOTA
python 写的一个爬虫程序源码
2016/02/28 Python
详解python中requirements.txt的一切
2017/03/03 Python
python爬虫_微信公众号推送信息爬取的实例
2017/10/23 Python
python多线程并发让两个LED同时亮的方法
2019/02/18 Python
python实现画循环圆
2019/11/23 Python
Python使用QQ邮箱发送邮件报错smtplib.SMTPAuthenticationError
2019/12/20 Python
浅谈keras的深度模型训练过程及结果记录方式
2020/01/24 Python
python 利用Pyinstaller打包Web项目
2020/10/23 Python
CSS3利用text-shadow属性实现多种效果的文字样式展现方法
2016/08/25 HTML / CSS
canvas实现手机的手势解锁的步骤详细
2020/03/16 HTML / CSS
Marc Jacobs官方网站:美国奢侈品牌
2017/08/29 全球购物
求职信需要的五点内容
2014/02/01 职场文书
表决心的诗句大全
2014/03/11 职场文书
厨师个人自我鉴定范文
2014/04/19 职场文书
高中生操行评语
2014/04/25 职场文书
确保工程质量承诺书
2015/04/29 职场文书
催款函怎么写
2015/06/24 职场文书
纪委立案决定书
2015/06/24 职场文书
孙振耀退休感言
2015/08/01 职场文书
司法廉洁教育心得体会
2016/01/20 职场文书
纯html+css实现奥运五环的示例代码
2021/08/02 HTML / CSS