数组去重:将数组中重复的元素找出来并删减为一个。目的很简单,方法倒有很多,以至于我费尽心思去考虑各种方法的好处坏处并进行对比,最终得出在各种场合适用的不同方法。希望有不同意见的尽管指出来。
【方法1】:
/*
* function unique1(array)
* 原理:新定义一个数组,结合一个对象辅助
* 时间复杂度:O(n)
* 适用范围:全数字、全字符串
* 方法缺点:混淆数字与数字字符串,对于对象无效
*/
functionunique1(array){
if(!array)returnarray;
varobj ={},a =[];
for(vari =0,iLen =array.length;i
if(!obj[array[i]]){
a.push(array[i]);
obj[array[i]]=true;
}
}
returna;
}
简单易懂的方法,但是对于只含数字的字符串(如 '12')无法和数字区分开来,对于对象也无法区分,可以在底部的测试例子中看到。
【方法2】:
/*
* function unique2(arr)
* 原理:新定义一个数组,结合一个对象辅助
* 时间复杂度:O(n)
* 适用范围:全数字、全字符串、数字与字符串混合
* 方法缺点:对于对象,所有对象最后只剩一个(不管键值对是否相同)
*/
functionunique2(array){
if(!array)returnarray;
varobj ={},a =[];
for(vari =0,iLen =array.length;i
if((typeofobj[array[i]])!=(typeofarray[i])||obj[array[i]]!=array[i]){
a.push(array[i]);
obj[array[i]]=array[i];
}
}o=obj;
returna;
}
这种方法在方法1的基础上,能够分辨出数字字符串和数字,但对于对象仍无能为力。
【方法3】:
/*
* function uniqExceptObj(array)
* 原理:查找相同值,对数组进行splice修改
* 时间复杂度:O(n2)
* 适用范围:全数字、全字符串、数字与字符串混合、含有对象(不同对象的键值对均不同)
* 方法缺点:无法区分具有相同键值对的不同对象
* 注意!array.length不要事先获取,如 iLen=array.length; 因为循环过程中array.length会变化
*/
functionuniqExceptObj(array){
vartemp =array.slice(0);//设置一个辅助数组,避免直接修改原array数组
for(vari =0;i
for(varj =i +1;j
if(temp[i]===temp[j]){
temp.splice(j,1);
j--;
}
}
}
returntemp;
}
现在,对于对象也可以区分了。但是仍然无法区分具有相同键值对的不同对象,那么这也不是真正意义上的去重。并且,时间复杂度已经达到了O(n2)了。
【方法4】:
/*
* function uniqueAll(array)
* 原理:用equal函数查找相同值,对数组进行splice修改
* 时间复杂度:O(n3)
* 适用范围:全部
* 方法缺点:复杂度太大,时间消耗太大
* 说明:内置辅助函数 isEqual
* 注意!array.length不要事先获取,如 iLen=array.length;
*/
functionuniqueAll(array){
/* function isEqual(obj1,obj2)
* 功能:比较任何类型的两个元素
* 结果:只有两个元素类型相同且值相同时才返回真
*/
functionisEqual(obj1,obj2){
if(obj1 ===obj2){returntrue;}
if(!(obj2 instanceofObject)||(obj2 ===null)){returnfalse;}// null is not instanceof Object.
varp =0;// count propoty of obj1
for(vark inobj1){
p++;
varo1 =obj1[k];
varo2 =obj2[k];
if((o1 !=null)&&!(isEqual(o1,o2))){returnfalse;}// compare inner object.
}
for(vark inobj2){// compare object property counter.
p--;
}
returnp ==0;
}
vartemp =array.slice(0);//设置一个辅助数组,避免直接修改原array数组
for(vari =0;i
for(varj =i +1;j
if(isEqual(temp[i],temp[j])){
temp.splice(j,1);
j--;
}
}
}
returntemp;
}
仍是用方法3的思路,把各个数组元素进行对比,只是在对比时用了一个内置函数isEqual,用来有效地比较各种类型,包括对象。这种方法可以有效地对任何类型数据进行处理,但缺点明显,时间复杂度O(n3)。所以,在不需要对对象处理的时候,还是避免使用的好。
【终于到结论了】:
从以上的各种对比来看,我们可以得出一个前人早已得出的结论:“人无完人,金无足赤”。各个方法有各自不同的优点和缺点。
当只需要处理字符串或只需要处理数字时,我们可以采用方法1;
当需要处理字符串和数字混合的数组而无需处理对象时,我们采用方法2;
当只需处理去掉同个对象而不需处理多个键值对相同的对象时,可以采用方法3;
当要求对不同对象但键值对相同的对象进行去重时,我们可以采用方法4。
原址:http://chanthuang.blog.163.com/blog/static/16812743820133725815167/