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

类似的问题:

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


当前回答

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

其他回答

任务是从由任意类型(基元和非基元)组成的数组中获取唯一的数组。

基于使用新集合(…)的方法不是新的。这里它被JSON.stringify(…)、JSON.parse(…)和[].map方法所利用。其优点是通用性(适用于任何类型的数组)、简短的ES6表示法以及在这种情况下的性能:

常量重复数据消除示例=[{a:1},{a:1},[ 1, 2 ],[ 1, 2 ],1.1.'1','1']常量getUniqArrDeep=arr=>{const arrStr=arr.map(项=>JSON.stringify(项))return[…新集合(arrStr)].map(item=>JSON.parse(item))}console.info(getUniqArrDeep(重复数据消除示例))/*[{a:1},[1,2],1,“1”]*/

我们可以使用ES6集合来实现这一点:

var duplicatesArray=[1,2,3,4,5,1,1,2,4,4];var uniqueArray=[…new Set(duplicatesArray)];console.log(uniqueArray);//[1,2,3,4,5]

最简单、最快(在Chrome中)的方法:

Array.prototype.unique = function() {
    var a = [];
    for (var i=0, l=this.length; i<l; i++)
        if (a.indexOf(this[i]) === -1)
            a.push(this[i]);
    return a;
}

只需遍历数组中的每个项,测试该项是否已经在列表中,如果没有,则推送到返回的数组。

根据JSBench的说法,这个函数是我在任何地方都能找到的最快的函数——尽管可以随意添加自己的函数。

非原型版本:

function uniques(arr) {
    var a = [];
    for (var i=0, l=arr.length; i<l; i++)
        if (a.indexOf(arr[i]) === -1 && arr[i] !== '')
            a.push(arr[i]);
    return a;
}

排序

当还需要对阵列进行排序时,以下是最快的:

Array.prototype.sortUnique = function() {
    this.sort();
    var last_i;
    for (var i=0;i<this.length;i++)
        if ((last_i = this.lastIndexOf(this[i])) !== i)
            this.splice(i+1, last_i-i);
    return this;
}

或非原型:

function sortUnique(arr) {
    arr.sort();
    var last_i;
    for (var i=0;i<arr.length;i++)
        if ((last_i = arr.lastIndexOf(arr[i])) !== i)
            arr.splice(i+1, last_i-i);
    return arr;
}

在大多数非Chrome浏览器中,这也比上述方法更快。

魔术

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

重复数据消除通常需要给定类型的相等运算符。然而,使用eq函数会阻止我们以有效的方式使用Set来确定重复项,因为Set返回到==。如您所知,==不适用于引用类型。所以,如果被卡住了,我们会很好,对吧?

解决方法是简单地使用一个转换器函数,它允许我们将一个(引用)类型转换为我们可以使用Set实际查找的类型。例如,如果数据结构不包含任何函数,我们可以使用哈希函数或JSON.stringify数据结构。

通常我们只需要访问一个属性,然后我们就可以比较它而不是Object的引用。

以下是满足这些要求的两个组合子:

常量重复数据消除On=k=>xs=>{const s=new Set();返回xs.filter(o=>s有(o[k])? 无效的:(s.add(o[k]),o[k]]);};常量重复数据消除By=f=>xs=>{const s=new Set();返回xs.filter(x=>{常量r=f(x);返回s.has(r)? 无效的:(s.add(r),x);});};const xs=[{foo:“a”},{foo:“b”};控制台日志(重复数据删除打开(“foo”)(xs));//〔{foo:“a”},{foo:“b”}、{foo:“a”}和{foo:“c”}〕控制台日志(重复数据删除方式(o=>o.foo.toLowerCase())(xs));//〔{foo:“a”}、{foo:“b”},{foo:“c”}〕

使用这些组合器,我们可以非常灵活地处理各种重复数据消除问题。这不是禁食的方法,而是最具表现力和通用性的方法。