我有一个对象数组。我试图找到重复的对象,然后删除该对象的两个实例。
现在我正在使用这种方法:
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;
}
我认为问题在于它只检查索引大于它正在检查的当前位置的重复项。这意味着不会检查数组中“后面”的对象是否有重复。目前,我通过此函数运行数组几次以获得所需的结果。然而,这显然是非常低效的。我怎样才能更有效地实现我想要的结果?
答案 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#some
,Function#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。