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

类似的问题:

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


当前回答

使用Set删除重复项。

具有重复项的阵列

const withDuplicates = [2, 2, 5, 5, 1, 1, 2, 2, 3, 3];

使用Set获取不重复的新数组

const withoutDuplicates = Array.from(new Set(withDuplicates));

较短版本

const withoutDuplicates = [...new Set(withDuplicates)];

结果:[2,5,1,3]

其他回答

在其他答案的基础上,这里有另一个变体,它使用可选标志来选择策略(保持第一次出现或保持最后一次出现):

不扩展Array.prototype

function unique(arr, keepLast) {
  return arr.filter(function (value, index, array) {
    return keepLast ? array.indexOf(value, index + 1) < 0 : array.indexOf(value) === index;
  });
};

// Usage
unique(['a', 1, 2, '1', 1, 3, 2, 6]); // -> ['a', 1, 2, '1', 3, 6]
unique(['a', 1, 2, '1', 1, 3, 2, 6], true); // -> ['a', '1', 1, 3, 2, 6]

扩展Array.prototype

Array.prototype.unique = function (keepLast) {
  return this.filter(function (value, index, array) {
    return keepLast ? array.indexOf(value, index + 1) < 0 : array.indexOf(value) === index;
  });
};

// Usage
['a', 1, 2, '1', 1, 3, 2, 6].unique(); // -> ['a', 1, 2, '1', 3, 6]
['a', 1, 2, '1', 1, 3, 2, 6].unique(true); // -> ['a', '1', 1, 3, 2, 6]

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

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

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]);
    }
  }
};

看来我们已经失去了拉斐尔的答案,这是几年来公认的答案。如果没有混合类型数组,这是(至少在2017年)性能最好的解决方案:

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

如果您有混合类型数组,则可以序列化哈希键:

Array.prototype.getUnique = function() {
    var hash = {}, result = [], key; 
    for ( var i = 0, l = this.length; i < l; ++i ) {
        key = JSON.stringify(this[i]);
        if ( !hash.hasOwnProperty(key) ) {
            hash[key] = true;
            result.push(this[i]);
        }
    }
    return result;
}

这里的许多答案可能对初学者没有帮助。如果数组的重复数据消除很困难,他们真的会知道原型链,甚至jQuery吗?

在现代浏览器中,一个干净而简单的解决方案是将数据存储在一个集合中,该集合被设计为一个唯一值列表。

const cars=[“沃尔沃”、“吉普”、“沃尔沃”,“林肯”、“林肯”和“福特”];constuniqueCars=Array.from(新集合(cars));console.log(uniqueCars);

Array.from用于将Set转换回Array,以便您可以轻松访问数组所具有的所有很棒的方法(功能)。同样的事情还有其他方法。但您可能根本不需要Array.from,因为Sets有很多有用的功能,比如forEach。

如果您需要支持旧的Internet Explorer,因此无法使用Set,那么一种简单的方法是将项目复制到新阵列中,同时预先检查它们是否已在新阵列中。

// Create a list of cars, with duplicates.
var cars = ['Volvo', 'Jeep', 'Volvo', 'Lincoln', 'Lincoln', 'Ford'];
// Create a list of unique cars, to put a car in if we haven't already.
var uniqueCars = [];

// Go through each car, one at a time.
cars.forEach(function (car) {
    // The code within the following block runs only if the
    // current car does NOT exist in the uniqueCars list
    // - a.k.a. prevent duplicates
    if (uniqueCars.indexOf(car) === -1) {
        // Since we now know we haven't seen this car before,
        // copy it to the end of the uniqueCars list.
        uniqueCars.push(car);
    }
});

为了使其立即可重用,让我们将其放在函数中。

function deduplicate(data) {
    if (data.length > 0) {
        var result = [];

        data.forEach(function (elem) {
            if (result.indexOf(elem) === -1) {
                result.push(elem);
            }
        });

        return result;
    }
}

所以为了消除重复,我们现在就这样做。

var uniqueCars = deduplicate(cars);

当函数完成时,重复数据消除(cars)部分将成为我们命名为result的部分。

只需将您喜欢的任何数组的名称传递给它即可。

你根本不需要.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 */
}