如何删除数组中重复对象的两个实例

How to remove both instances of duplicated objects in an array

本文关键字:对象 实例 两个 何删除 删除 数组      更新时间:2023-09-26

我有一个对象数组。我试图找到重复的对象,然后删除该对象的两个实例。

现在我正在使用这个方法:

function checkForDups(data){
    for(var i = 0; i < data.length; i++){
      for(var j = i+1; j < data.length; j++){
        if(data[j].number === data[i].number){
          data.splice(j,1);
          data.splice(i,1);
        }
      }
    }
    return data;
  }

我认为问题是它只检查索引大于当前位置的重复项。这意味着在数组中"后面"的对象不会被检查是否重复。目前,我通过这个函数运行数组几次以获得所需的结果。然而,这显然是极其低效的。我怎样才能更有效地达到我想要的结果?

我认为问题是它只检查索引大于当前位置的重复项。这意味着在数组中"后面"的对象不会被检查是否重复。

不,这是一个简单的优化,通过相等关系的对称性使之成为可能。通过提前搜索并删除你面前的所有重复项,任何当前项都不能是前一个项的重复项,否则它就已经被消除了。

然而,有一些事情你没有注意到:

  • 当从数组中拼接(删除)一个项目时,所有后续的项目都会被移动,数组的长度也会改变。要真正检查数组中的所有项目,您需要在删除时减少(或:不增加)计数器变量,以便访问现在与被删除的项目在同一位置的新项目(您刚刚删除的地点需要重新访问)。
  • 您可能希望在找到重复项后将内循环break,否则您将比较并删除完全不同的项。
  • 你还没有明确的算法应该做什么,当有超过2个相同排序的重复项目在数组中。如果对方的号码是奇数,留下一个?谢谢你的评论。
    要删除所有现有的重复项,您需要继续搜索,但一定不要立即删除i th元素,否则您将没有任何东西可以进一步比较-或者您甚至可能多次删除i th项(参见#2)。

所以这个修改应该适合:

function removeAllDups(data) {
    // leaves only items in the array that appeared a single time
    // removes everything whose .number can be found multiple times
    for (var i = 0; i < data.length; i++) {
        var found = false,
            num = data[i].number;
        for (var j = i+1; j < data.length; j++) {
            if (data[j].number === num) {
                found = true;
                data.splice(j--, 1);
            }
        }
        if (found) {
            data.splice(i--, 1);
        }
    }
    return data;
}

这是另一种实现。这只使用两次遍历数组,并在情况> 2时删除所有重复:http://jsfiddle.net/nrabinowitz/1pdr780j/

function removeDupes(arr, test) {
    test = test || function(a, b) { return a === b; };
    function find(cache, element) {
        return cache.some(test.bind(null, element));
    }
    var seen = [];
    var dupes = [];
    var len = arr.length;
    var x;
    var current;
    // First pass - find dupes
    for (x = 0; x < len; x++) {
        current = arr[x];
        if (find(seen, current)) {
            dupes.push(current);
        } else {
            seen.push(current);
        }
    }
    // Second pass: remove dupes. Reverse iteration saves headaches here
    for (x = len - 1; x >= 0; x--) {
        current = arr[x];
        if (find(dupes, current)) {
            arr.splice(x, 1);
        }
    }
}

这是一个更新的版本,它采用一个可选的测试函数来确定是否相等。对于OP的情况,调用将是

removeDupes(arr, function(a, b) {
    return a.number == b.number;
});

注意,这假设支持ES5方法- Array#some, Function#bind。如果你需要支持旧的浏览器,一个ES5 shim或者Underscore库就可以了。

您可以使用underscore.js:

function checkForDups(data) {
  return (
    _.map(
      _.filter(
        _.pairs(
          _.countBy(data)
        ), function(v) {return v[1] == 1}
      ), function(v) {return ~~v[0]}
    )
  )
}

>> console.log(checkForDups([0,1,2,3,0,1,0,4]))
[2, 3, 4]