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

类似的问题:

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


当前回答

这并不是对原始问题的直接字面回答,因为我更希望在数组中首先不要有重复的值。这是我的UniqueArray:

class UniqueArray extends Array {
    constructor(...args) {
        super(...new Set(args));
    }
    push(...args) {
        for (const a of args) if (!this.includes(a)) super.push(a);
        return this.length;
    }
    unshift(...args) {
        for (const a of args.reverse()) if (!this.includes(a)) super.unshift(a);
        return this.length;
    }
    concat(...args) {
        var r = new UniqueArray(...this);
        for (const a of args) r.push(...a);
        return r;
    }
}
> a = new UniqueArray(1,2,3,1,2,4,5,1)
UniqueArray(5) [ 1, 2, 3, 4, 5 ]
> a.push(1,4,6)
6
> a
UniqueArray(6) [ 1, 2, 3, 4, 5, 6 ]
> a.unshift(1)
6
> a
UniqueArray(6) [ 1, 2, 3, 4, 5, 6 ]
> a.unshift(0)
7
> a
UniqueArray(7) [
  0, 1, 2, 3,
  4, 5, 6
]
> a.concat(2,3,7)
UniqueArray(8) [
  0, 1, 2, 3,
  4, 5, 6, 7
]

其他回答

ES2016.includes()一种方法简单答案:

var arr = [1,5,2,4,1,6]
function getOrigs(arr) {
  let unique = []
  arr && arr.forEach(number => {
    !unique.includes(number) && unique.push(number)
    if (number === arr[arr.length - 1]) {
      console.log('unique: ', unique)
    }
  })
}
getOrigs(arr)

请改用此选项:

更新的ES版本简单问题不应使用多个高级JS方法,push()、length()和forEach()是常见的使用闭包更容易阅读在内存、垃圾收集和性能方面似乎比其他产品更好更少的代码行:如果您根据行结尾的位置分隔行,则只需要一行逻辑(因此您可以根据需要调用或重构这一行):

var arr = [1,5,2,4,1,6];
function getOrigs(arr) {let unique = []; 
  arr && arr.forEach(number => !unique.includes(number) && unique.push(number) && ((number === arr[arr.length - 1]) && console.log('unique: ', unique)))};
getOrigs(arr);

很多人已经提到使用。。。

[...new Set(arr)];

这是一个很好的解决方案,但我的首选是与.filter一起使用的解决方案。在我看来,filter是获取唯一值的更自然的方法。您可以有效地删除重复项,而从数组中删除元素正是过滤器的作用所在。它还允许您链接.map、.reduce和其他.filter调用。我设计了这个解决方案。。。

const unique = () => {
  let cache;  
  return (elem, index, array) => {
    if (!cache) cache = new Set(array);
    return cache.delete(elem);
  };
};

myArray.filter(unique());

需要注意的是,你需要一个结束,但我认为这是一个值得的权衡。就性能而言,它比我看到的使用.filter的其他解决方案更具性能,但比[…new Set(arr)]性能更差。

另请参阅我的github包

如前所述,[…new Set(value)]是最好的选项,如果您可以使用的话。

否则,这里有一个单行程序,它不会为每个索引迭代数组:

values.sort().filter((val, index, arr) => index === 0 ? true : val !== arr[index - 1]);

这只是将每个值与前面的值进行比较。结果将被排序。

例子:设值=[1,2,3,3,4,5,5,4,4,3,1,1,3,3];let unique=values.sort().filter((val,index,arr)=>索引==0?真:val!==arr[索引-1]);console.log(唯一);

设ar=[1,2,3,4,5,6,1,2,4,2,1];let unique=ar.filter((值,索引)=>{return ar.indexOf(value)==索引;});console.log(唯一);

魔术

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)))