我有一组数字,我需要确保它们是唯一的。我在互联网上找到了下面的代码片段,它工作得很好,直到数组中有一个零。我在Stack Overflow上找到了另一个脚本,看起来几乎与它完全一样,但它不会失败。

所以为了帮助我学习,有人能帮我确定原型脚本哪里出错吗?

Array.prototype.getUnique = function() {
 var o = {}, a = [], i, e;
 for (i = 0; e = this[i]; i++) {o[e] = 1};
 for (e in o) {a.push (e)};
 return a;
}

重复问题的更多答案:

从JS数组中删除重复值

类似的问题:

获取数组中的所有非唯一值(即:重复/多次出现)


当前回答

这个不是纯的,它会修改数组,但这是最快的。如果你的速度更快,请写下评论;)

http://jsperf.com/unique-array-webdeb

Array.prototype.uniq = function(){
    for(var i = 0, l = this.length; i < l; ++i){
        var item = this[i];
        var duplicateIdx = this.indexOf(item, i + 1);
        while(duplicateIdx != -1) {
            this.splice(duplicateIdx, 1);
            duplicateIdx = this.indexOf(item, duplicateIdx);
            l--;
        }
    }

    return this;
}

[
 "",2,4,"A","abc",
 "",2,4,"A","abc",
 "",2,4,"A","abc",
 "",2,4,"A","abc",
 "",2,4,"A","abc",
 "",2,4,"A","abc",
 "",2,4,"A","abc",
 "",2,4,"A","abc"
].uniq() //  ["",2,4,"A","abc"]

其他回答

魔术

a.filter(e=>!(t[e]=e in t)) 

O(n)性能-我们假设您的阵列位于a中,且t={}。此处解释(+Jeppe impr.)

让unique=(a,t={})=>a.filter(e=>!(t〔e〕=e in t));//使用全局t的“单机”版本://a1.过滤器((t={},e=>!(t[e]=e in t));//测试数据设a1=[5,6,0,4,9,2,3,5,0,3,4,1,5,4,9];设a2=[[2,17],[2,17]、[2,17]、[1,12]、[5,9]、[1,12]、[6,2],[1,12]];设a3=[“迈克”、“亚当”、“马特”、“南希”、“亚当斯”、“珍妮”、“南茜”、“卡尔”];//结果console.log(JSON.stringify(唯一(a1)))console.log(JSON.stringify(唯一(a2)))console.log(JSON.stringify(唯一(a3)))

还有另一个答案,只是因为我为我的特定用例写了一个答案。我碰巧正在对阵列进行排序,如果我正在排序,我可以使用它来消除重复数据。

注意,我的排序处理我的特定数据类型,您可能需要不同的排序,这取决于您拥有的元素类型。

var sortAndDedup = function(array) {
  array.sort(function(a,b){
    if(isNaN(a) && isNaN(b)) { return a > b ? 1 : (a < b ? -1 : 0); }
    if(isNaN(a)) { return 1; }
    if(isNaN(b)) { return -1; }
    return a-b;
  });

  var newArray = [];
  var len = array.length;
  for(var i=0; i<len; i++){
    if(i === 0 || array[i] != array[i-1]){
      newArray.push(array[i]);
    }
  }
};

对我来说,这是最简单的解决方案

//检查数组是否相等的方法常量a=['a','B','C'].sort().toString()常量b=['A','C','b'].sort().toString()console.log(a===b);//真的//测试用例常量数据=[{组:“A”,名称:“SD”},{组:“B”,名称:“FI”},{组:“A”,名称:“SD”},{组:“B”,名称:“CO”}];//返回一个不带重复定位的新数组函数唯一(数据){return data.reduce(函数(累加器,currentValue){//转换为字符串以检查它们是否为相同的值。const currentKeys=对象.keys(currentValue).sort().toString();const currentValues=对象.values(currentValue).sort().toString();let hasObject=falsefor(累加器的常量对象){//将键和值转换为字符串,以便我们可以//看看它们是否与当前值相等constkeys=对象.keys(obj).sort().toString();const values=Object.values(obj).sort().toString();//检查键和值是否相等if(keys==currentKeys&&values==currentValues){hasObject=真}}//如果对象不存在,则推送该对象。if(!hasObject){累加器推力(currentValue)}回流蓄能器}, []);}//运行测试用例console.log(唯一(数据));//[{组:“A”,名称:“SD”},{组为“B”,名称为“FI”}、{组“B”、名称为“CO”}]

这个原型getUnique并不完全正确,因为如果我有一个类似于[“1”,1,2,3,4,1,“foo”]的数组,它将返回[“1“,“2”,“3”,“4”],“1”是字符串,1是整数;它们是不同的。

以下是正确的解决方案:

Array.prototype.unique = function(a){
    return function(){ return this.filter(a) }
}(function(a,b,c){ return c.indexOf(a,b+1) < 0 });

使用:

var foo;
foo = ["1",1,2,3,4,1,"foo"];
foo.unique();

以上将产生[“1”,2,3,4,1,“foo”]。

我查看了Joeytje50在jsperf上的代码,他比较了许多替代方案。他的代码有很多小错误,这对性能和正确性产生了影响。

更重要的是,他正在一个非常小的阵列上进行测试。我用1000个整数组成了一个数组。每个整数是0到1000之间的随机整数的100倍。这使得平均约1000/e=368个重复。结果在jsperf。

这是一个可能需要效率的更现实的场景。这些变化使声明发生了戏剧性的变化(特别是被吹捧为最快的代码远没有快到哪里去)。明显的赢家是使用哈希技术的地方,最好的是

Array.prototype.getUnique3 = function(){
   var u = Object.create(null), a = [];
   for(var i = 0, l = this.length; i < l; ++i){
      if(this[i] in u) continue;
      a.push(this[i]);
      u[this[i]] = 1;
   }
   return a.length;
}