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

类似的问题:

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


当前回答

你根本不需要.indexOf();你可以这样做O(n):

function SelectDistinct(array) {
    const seenIt = new Set();

    return array.filter(function (val) {
        if (seenIt.has(val)) { 
            return false;
        }

        seenIt.add(val);

        return true;
    });
}

var hasDuplicates = [1,2,3,4,5,5,6,7,7];
console.log(SelectDistinct(hasDuplicates)) //[1,2,3,4,5,6,7]

如果不想使用.filter():

function SelectDistinct(array) {
    const seenIt = new Set();
    const distinct = [];

    for (let i = 0; i < array.length; i++) {
        const value = array[i];

        if (!seenIt.has(value)) {
            seenIt.add(value);
            distinct.push(value);
        }
    }
    
    return distinct; 
    /* you could also drop the 'distinct' array and return 'Array.from(seenIt)', which converts the set object to an array */
}

其他回答

使用lodash和identity lambda函数执行,只需在使用对象之前定义它

const _ = require('lodash');
...    
_.uniqBy([{a:1,b:2},{a:1,b:2},{a:1,b:3}], v=>v.a.toString()+v.b.toString())
_.uniq([1,2,3,3,'a','a','x'])

并且将具有:

[{a:1,b:2},{a:1,b:3}]
[1,2,3,'a','x']

(这是最简单的方法)

此脚本修改数组,过滤出重复的值。它适用于数字和字符串。

https://jsfiddle.net/qsdL6y5j/1/

    Array.prototype.getUnique = function () {
        var unique = this.filter(function (elem, pos) {
            return this.indexOf(elem) == pos;
        }.bind(this));
        this.length = 0;
        this.splice(0, 0, unique);
    }

    var duplicates = [0, 0, 1, 1, 2, 3, 1, 1, 0, 4, 4];
    duplicates.getUnique();
    alert(duplicates);

相反,此版本允许您返回具有唯一值的新数组,该值保持原始值(仅传递true)。

https://jsfiddle.net/dj7qxyL7/

    Array.prototype.getUnique = function (createArray) {
        createArray = createArray === true ? true : false;
        var temp = JSON.stringify(this);
        temp = JSON.parse(temp);
        if (createArray) {
            var unique = temp.filter(function (elem, pos) {
                return temp.indexOf(elem) == pos;
            }.bind(this));
            return unique;
        }
        else {
            var unique = this.filter(function (elem, pos) {
                return this.indexOf(elem) == pos;
            }.bind(this));
            this.length = 0;
            this.splice(0, 0, unique);
        }
    }

    var duplicates = [0, 0, 1, 1, 2, 3, 1, 1, 0, 4, 4];
    console.log('++++ ovveride')
    duplicates.getUnique();
    console.log(duplicates);
    console.log('++++ new array')
    var duplicates2 = [0, 0, 1, 1, 2, 3, 1, 1, 0, 4, 4];
    var unique = duplicates2.getUnique(true);
    console.log(unique);
    console.log('++++ original')
    console.log(duplicates2);

Browser support:

Feature Chrome  Firefox (Gecko)     Internet Explorer   Opera   Safari
Basic support   (Yes)   1.5 (1.8)   9                   (Yes)   (Yes)

这是因为0在JavaScript中是一个错误的值。

如果数组的值为0或任何其他错误值,则此[i]将是错误的。

这并不是对原始问题的直接字面回答,因为我更希望在数组中首先不要有重复的值。这是我的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
]

如果您有一个对象数组,并且需要uniqueBy函数,例如通过id字段:

function uniqueBy(field, arr) {
   return arr.reduce((acc, curr) => {
     const exists = acc.find(v => v[field] === curr[field]);
     return exists ? acc : acc.concat(curr);
   }, [])
}