我有一组数字,我需要确保它们是唯一的。我在互联网上找到了下面的代码片段,它工作得很好,直到数组中有一个零。我在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数组中删除重复值

类似的问题:

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


当前回答

这里有一个几乎是一行的O(n),保留了第一个元素,并且在这里你可以将你正在uniq'ing上的字段分开。

这是函数式编程中非常常见的技术——您可以使用reduce来构建返回的数组。因为我们这样构建数组,所以我们保证得到稳定的排序,这与[…new Set(array)]方法不同。我们仍然使用Set来确保没有重复,因此我们的累加器同时包含Set和我们正在构建的数组。

常量删除重复项=(arr)=>减少(([set,acc],item)=>集合有(item)?[set,acc]:[set.add(项目),(acc.push(项目)、acc)],[新设置(),[]])[1]

上述方法适用于简单值,但不适用于对象,类似于[…new Set(array)]的分解方式。如果项目是包含id属性的对象,您应该执行以下操作:

常量删除重复项=(arr)=>减少(([set,acc],item)=>集合有(item.id)?[set,acc]:[set.add(item.id),(acc.push(item),acc)],[新设置(),[]])[1]

其他回答

最简单的方法是将值转换为字符串,以过滤嵌套的对象值。

const uniq = (arg = []) => {
  const stringifyedArg = arg.map(value => JSON.stringify(value))
  return arg.filter((value, index, self) => {
    if (typeof value === 'object')
      return stringifyedArg.indexOf(JSON.stringify(value)) === index
    return self.indexOf(value) === index
  })
}

    console.log(uniq([21, 'twenty one', 21])) // [21, 'twenty one']
    console.log(uniq([{ a: 21 }, { a: 'twenty one' }, { a: 21 }])) // [{a: 21}, {a: 'twenty one'}]

这个解决方案应该非常快,并且在很多情况下都有效。

将索引数组项转换为对象键使用Object.keys函数var indexArray=[“hi”,“welcome”,“欢迎”,1,-9];var keyArray={};indexArray.forEach(函数(项){keyArray[item]=null;});var uniqueArray=对象.keys(keyArray);

永远记住,内置方法易于使用。但请记住,它们具有复杂性。

基本逻辑是最好的。没有隐藏的复杂性。

let list = [1, 1, 2, 100, 2] // your array
let check = {}
list = list.filter(item => {
    if(!check[item]) {
        check[item] = true
        return true;
    }
})

或使用,如果您需要将来遍历检查项(但会浪费内存),则使用check=[]

我查看了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;
}

我遇到了一个稍微不同的问题,需要从数组中删除具有重复id财产的对象。这奏效了。

让objArr=[{id:“123”}, {id:“123”}, {id:'456'}];objArr=objArr.reduce((acc,cur)=>[…acc.filter((obj)=>obj.id!==cur.id),cur], []);console.log(objArr);