西红柿爱番茄

Feed Rss

去除数组重复项

06.20.2010, Javascript, by .

前几天在QQ群里有人提出了一个关于动态插入DOM元素的问题,并由此引出了如何删除数组中重复项的讨论,为此我写了一个小函数来实现这个需求:

[javascript]
var pureMultil=function(arr){
var obj={};
var a = [];
for(var i=0,l=arr.length;i < l;i++){
if(!(arr[i] in obj)){
a.push(arr[i]);
}
obj[arr[i]]="";
}
return a;
}
[/javascript]

原理很简单:就是先把数组的项保存在一个obj字面量对象里,之后在循环中通过判断当前数组的项是否已然在obj字面对象里,并随着做不同的操作。

今天重新想到了这段代码,翻开来看看了,想到了操作符”&&”的运行机制,就利用它的特点(操作符”||”跟它正好相反):如果左边的判断为true就继续执行右边的操作。为此,修改了上面的实现方式:
[javascript]
var pureMultil=function (arr){
var obj={};
var a = [];
for(var i=0,l=arr.length;i < l;i++){
!(arr[i] in obj) && a.push(arr[i]) && (obj[arr[i]]="");
}
return a;
}
[/javascript]

通过测试,在同样的条件下,速度居然呈倍数提高~《测试用例1》,示例中另外的一种实现方式由hehe123提供,不过性能上欠佳。

============================================================================

2010-6-20 updates:

为了纠正Wait在评论中所提出的对数据类型的判断来正确的处理像这样的数组:[1,"1"]。修改了下代码:
[javascript]
var pureMultil=function (arr){
var obj={},a = [],m,n;
for(var i=0,l=arr.length;i < l;i++){
m = arr[i];
n = typeof m;
(obj[n+m] !== m) && a.push(m) && (obj[n+m] = m);
}
return a;
}
[/javascript]
或者使用obj的判断形式:
[javascript]
var pureMultil2=function (arr){
var obj={},a = [],m,n;
for(var i=0,l=arr.length;i < l;i++){
m = arr[i];
n = typeof m;
!((n+m) in obj) && a.push(m) && (obj[n+m] = "");
}
return a;
}
[/javascript]

代码中加入了对数据类型的判断,这在循环中可想而知在性能消耗上也更多了,情况不是很佳,衡量而行,或者另寻方案。《测试页面2

倒是如果使用普通的方式,倒显得性能最佳而且也无需字面量对象的创建和复杂的判断,虽然代码量上多了许多:《测试页面3
[javascript]
var include=function (arr,item){
for(var i=0,l=arr.length;i < l;i++){
if(arr[i] === item){
return true;
}
}
return false;
}

var normalPureMultil=function (arr){
var a=[];
for(var i=0,l=arr.length;i < l;i++){
if(!include(a,arr[i])){
a.push(arr[i]);
}
}
return a;
}
[/javascript]

总结:对于小数组形式的去除重复项,可以考虑上面代码精简的方案来处理,这样可以节省文件的大小;而如果是大数组(上千数目)来说,而且文件大小还可以凑合的话,使用普通的方式,还是比较合适的。

去除数组重复项 有 8 条回应

  1. 这个函数的问题在于它无法判断类型,如果数据是这样的
    [ 1,'1' ] 那么1和’1′还是被认为是重复的,尽管他们不重复。只有相同的类型(全是字符或者全是数字)才算是能正常的工作

    而使用 prop in obj 需要检查原型链,性能上不如hasOwnProperty好。
    而且循环体中两到三次的arr[i]调用不如缓存起来,这样性能更好.
    大概像下面这样

    var pureMulti2=function (arr){
    var obj={},a = [];
    for(var i=0,l=arr.length,t=null;i < l;i++){
    (!obj.hasOwnProperty( t = arr[i] ) ) && a.push( t ) && (obj[ t ]="");
    }
    return a;
    }

  2. 我测试了一下prop in obj 和 hasOwnProperty,不同的浏览器结果不同。但是大部分竟然是 in obj 更快一点。。上面说错了喔。

  3. 楼主写的很好呀,我学习了。

  4. 2010-06-20 在 23:14 Supersha

    确实,忽略了数据类型的差别,有待改善,多谢Wait~
    还有缓存arr[i]性能上也确实会更好,当时只为了在循环里尽量减少操作和代码,没考虑到,呵呵~

  5. 谢谢你的分享 我会再来的

  6. 好文章,喜欢!

  7. 思路很好啊、、学习了

  8. m = arr[i];
    n = typeof m;
    (obj[n+m] !== m) && a.push(m) && (obj[n+m] = m);
    这句代码怎么解释啊
    n+m不就是字符串“number1”了吗

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

*

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>