比较两个JavaScript数组并删除重复项

87

它目前能正常工作,是否有其他更好的方法可以移除一个数组中和另一个数组相同的元素?

<script>
var array1 = new Array("a","b","c","d","e","f");
var array2 = new Array("c","e");

for (var i = 0; i<array2.length; i++) {
    var arrlen = array1.length;
    for (var j = 0; j<arrlen; j++) {
        if (array2[i] == array1[j]) {
            array1 = array1.slice(0, j).concat(array1.slice(j+1, arrlen));
        }
    }
}
alert(array1);

</script>

我可能错了,但我不认为这会有很好的性能。您正在执行两个循环。 - PositiveGuy
8个回答

221

2
作为上述代码的附注和解释:“indexOf:返回数组中等于指定值的元素的第一个(最小)索引,如果没有找到,则返回-1。”(https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FGlobal_Objects%2FArray) - Cedric
2
我喜欢它,但肯定需要解释,或者至少提供一个链接引导某人到正确的地方进行解释。 - Chris Cirefice
2
很棒的代码,尽管要注意如果有嵌套数组它将无法工作。 - kevinmicke
适用于唯一值列表的工作非常出色,但是对于其中包含重复项的列表呢?例如将“赎金笔记”与杂志中的单词列表进行比较(假设大小写必须匹配,并且每个单词的数量必须正确)... - CSS
它对我起作用了。(array1 = array1.filter(val => !array2.includes(val));)。谢谢。 :) - t4thilina
虽然这是一个不错的解决方案,但如果用户想要支持IE浏览器,则包含文件会出现问题。 - Sachin Jagtap

10

这个技巧,出于我无法理解的原因,是将外层循环向下递减(i--),将内层循环向上递增(j++)。

参考以下示例:

function test() {
  var array1 = new Array("a","b","c","d","e","f");
  var array2 = new Array("c","e");
  for (var i = array1.length - 1; i >= 0; i--) {
    for (var j = 0; j < array2.length; j++) {
      if (array1[i] === array2[j]) {
        array1.splice(i, 1);
        }
      }
    }
    console.log(array1)
  }

我怎么知道这个?看下面:

for( var i =myArray.length - 1; i>=0; i--){
  for( var j=0; j<toRemove.length; j++){
    if(myArray[i] === toRemove[j]){
      myArray.splice(i, 1);
    }
  }
}
或者
var myArray = [
  {name: 'deepak', place: 'bangalore'}, 
  {name: 'chirag', place: 'bangalore'}, 
  {name: 'alok', place: 'berhampur'}, 
  {name: 'chandan', place: 'mumbai'}
];
var toRemove = [
  {name: 'deepak', place: 'bangalore'},
  {name: 'alok', place: 'berhampur'}
];

for( var i=myArray.length - 1; i>=0; i--){
    for( var j=0; j<toRemove.length; j++){
        if(myArray[i] && (myArray[i].name === toRemove[j].name)){
            myArray.splice(i, 1);
        }
    }
}

alert(JSON.stringify(myArray));

在此提醒一下,有人能否解释一下为什么外层循环需要向下 (--)?

祝好运!


你不使用数组字面量、过滤器或包含函数的原因是什么? - Drenai
如何在不使用属性名称的情况下删除重复项,例如不指定任何数组对象名称。 - vishal
@vishal 将 array1[i] === array2[j] 更改为扩展该项的属性名称。这样就变成了 array1[i].propertyOfThisItem === array2[j].possiblyTheSameProperty - Cooper Scott

6
使用Set.prototype构造函数:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Set
let array1 = Array('a', 'b', 'c', 'd', 'e', 'f')
let array2 = Array('c', 'e', 'g')
let concat = array1.concat(array2) // join arrays => [ 'a', 'b', 'c', 'd', 'e', 'f', 'c', 'e', 'g' ]

// Set will filter out duplicates automatically
let set = new Set(concat) // => Set { 'a', 'b', 'c', 'd', 'e', 'f', 'g' }

// Use spread operator to extend Set to an Array
let result = [...set]
console.log(result) // =>  [ 'a', 'b', 'c', 'd', 'e', 'f', 'g' ]

1
这非常棒。使用Set和MDN链接中的示例函数可以实现非常巧妙的并集(回答了问题),差集和交集。我猜如果您首先将对象字符串化,它也可以用于对象(否则使用===)。 - Drenai
@Drenai 是的,如果你将对象转换为字符串,它就可以工作了 :) - Flavio

6

你可以试试这个

array1 = array1 .filter(val => {
             return !array2.find((val2)=>{
              //  console.log({valueID:val.id+":"+val2.id});
                return val.id===val2.id
             }) 
            });

2

使用Array.splice()方法

var array1 = ['1', '2', '3', '4', '5'];
var array2 = ['4', '5'];
var index;
for (var i=0; i<array2.length; i++) {
    index = array1.indexOf(array2[i]);
    if (index > -1) {
        array1.splice(index, 1);
    }
}

2

这是我在 ES6 中移除重复项的解决方案。

let foundDuplicate = false;
existingOptions.some(existingItem => {
  result = result.filter(item => {
    if (existingItem.value !== item.value) {
      return item;
    } else {
      foundDuplicate = true;
    }
  });
  return foundDuplicate;
});

我使用这种方法是因为我的情况下,我有一个对象数组,而indexOf在处理它时出现了问题。


1
这是我的解决方案: array1 = array1.filter(function(val) { return array2.indexOf(val.toString()) == -1; }); 它涉及到数组过滤和查找。

顶部答案不够吗?为什么需要额外的.toString()呢? - General Grievance

0
window.onload = function () {
        var array1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm'];
        var array2 = ['c', 'h', 'k'];
        var array3 = [];
        var SecondarrayIndexcount = 0;
        for (var i = 0; i < array1.length; i++) {
            for (var j = 0; j < array2.length; j++) {
                if (array1[i] !== array2[j]) {
                    if (SecondarrayIndexcount === (array2.length - 1)) {
                        array3.push(array1[i]);
                        SecondarrayIndexcount = 0;
                        break;
                    }
                    SecondarrayIndexcount++;
                }
            }
        }
        for (var i in array3) {
            alert(array3[i]);
        }
    }
</script>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接