数组中的键值对去重_数组去重-

数组去重:将数组中重复的元素找出来并删减为一个。目的很简单,方法倒有很多,以至于我费尽心思去考虑各种方法的好处坏处并进行对比,最终得出在各种场合适用的不同方法。希望有不同意见的尽管指出来。

【方法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/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值