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,只求在满足需求的基础上使程序效率更高!
关于js数组去重的问题小结
声明:登载此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述。
Reply on: @reply_date@
@reply_contents@