分享

删除数组中重复项(uniq)

 maoj66 2012-10-29

首先让我们看下 YUI 是如何处理的:

var toObject = function(a) {
   
var o = {};
   
for (var i = 0; i < a.length; i = i+1) {
     o
[a[i]] = true;
   
}
   
return o;
};

var keys = function(o) {
   
var a=[], i;
   
for (i in o) {
       
if (lang.hasOwnProperty(o, i)) { // YUI的方法
            a
.push(i);
       
}
   
}
   
return a;
};

var uniq = function(a) {
   
return keys(toObject(a));
};

详细分析,见同事 长天 的分享 《巧妙去除数组中的重复项》

自己使用的方式与 YUI 的方式十分相似,不过仅使用了一次循环便完成了删除数组中重复项,如下:

var uniq = function (arr) {
   
var a = [],
        o
= {},
        i
,
        v
,
        len
= arr.length;

   
if (len < 2) {
       
return arr;
   
}

   
for (i = 0; i < len; i++) {
        v
= arr[i];
       
if (o[v] !== 1) {
            a
.push(v);
            o
[v] = 1;
       
}
   
}

   
return a;
}

经过了简单的测试:自己使用的方式性能远远高于 YUI 的方式。

抛砖引玉,欢迎大家提供更好的处理方法。

2009年12月28日更新:

以上两种函数方法暂时都不能处理复杂的含有混合类型的数组(感谢 小猫 提出的疑问),如:[0,"0",1,"1",0]、["null",null]。

对于能够约定类型为数字(注:要求非0开头的数字,小数除外)或字符串的数组,我们可以用改进后的函数方法(感谢 closurecache 提供的思路):

var uniq = function (arr) {
   
var a = [],
        o
= {},
        i
,
        v
,
        cv
, // corrected value
        len
= arr.length;

   
if (len < 2) {
       
return arr;
   
}

   
for (i = 0; i < len; i++) {
        v
= arr[i];

       
/* closurecache 提供的函数中使用的是  cv = v + 0;,
         * 这样就无法辨别类似[1, 10, "1", "10"]的数组,
         * 因为运算后 => 1, 10, 10, 100,很明显,出现了重复的标示符。
         * 加前面就难道没问题吗?
         * 有的:数组中不能出现类似01 、001,以 0 开头的数字,
         * 但适用性比原先更广。
         */

        cv
= 0 + v;

       
if (!o[cv]) {
            a
.push(v);
            o
[cv] = true;
       
}
   
}

   
return a;
}

如果大家想在此解题思路的基础上,更完美一点,推荐 Dexter.Yy 的方法,进行类型判断,给予唯一标示符,详见 评论 20 楼

没有最好,只有最合适的方式,其实使用 Array.indexOf() 的思路也是不错的选择,对于已经支持的浏览器直接用原生的 Array.indexOf() 方法,对于未支持的,我们增加 Array.indexOf() 方法,如下:

if(!Array.prototype.indexOf) {
   
Array.prototype.indexOf = function (obj, fromIndex) {
       
if (fromIndex == null) {
            fromIndex
= 0;
       
} else if (fromIndex < 0) {
            fromIndex
= Math.max(0, this.length + fromIndex);
       
}

       
for (var i = fromIndex; i < this.length; i++) {
           
if (this[i] === obj)
               
return i;
           
}
       
return -1;
   
};
}

接下来,实现的过程就非常简单了。

对于使用 Array.indexOf() 方法实现方案的优化提示:找到相同值时,从数组中移除,以减少下次遍历的量。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多