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

时间:2014-08-14 16:12:15

标签: javascript arrays object

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

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

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

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

3 个答案:

答案 0 :(得分:1)

  

我认为问题在于它只检查索引大于它正在检查的当前位置的重复项。这意味着&#34;背后的对象&#34;不检查数组中的它是否重复。

不,这是一种简单的优化,通过平等关系的对称性而成为可能。通过提前搜索并删除您面前的所有副本,任何当前项目都不能与之前的项目重复,或者它已经被淘汰。

但是,有些事情你没有照顾:

  • 从数组中拼接(移除)项目时,将移动所有后续项目,并且数组会更改其长度。要真正检查数组中的所有项目,您需要在删除时减少(或者不增加)计数器变量,以便现在与已删除的项目位于同一位置的新项目(您刚从中删除的位置)需要重新审视)。
  • 您可能希望break找到重复后的内循环,否则您将比较并删除完全不同的项目。
  • 当数组中有两个以上相同类型的重复项时,您还没有明确算法应该做什么。当他们的号码是奇数时留一个?感谢您的评论 要删除所有现有重复项,您需要继续搜索,但不能立即删除i元素,否则您将无法与其进行比较 - 或者您甚至可能删除{{1这个项目多次(见#2)。

所以这个修改应该适合:

i

答案 1 :(得分:0)

这是一个替代实现。这仅使用两次遍历数组,并且在&gt;情况下移除所有欺骗。 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#someFunction#bind。如果您需要支持较旧的浏览器,ES5垫片或Underscore库将符合要求。

答案 2 :(得分:0)

您可以使用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]

您可以尝试here