我正在寻找一种有效的方法,从javascript数组中删除所有元素,如果它们存在于另一个数组中。

// If I have this array:
var myArray = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];

// and this one:
var toRemove = ['b', 'c', 'g'];

我想对myArray进行操作,使其处于这种状态:['a', 'd', 'e', 'f']

与jQuery,我使用grep()和inArray(),这工作得很好:

myArray = $.grep(myArray, function(value) {
    return $.inArray(value, toRemove) < 0;
});

有没有一个纯javascript的方法来做到这一点没有循环和剪接?


当前回答

使用Array.filter()方法:

myArray = myArray.filter( function( el ) {
  return toRemove.indexOf( el ) < 0;
} );

小小的改进,因为浏览器对Array.includes()的支持增加了:

myArray = myArray.filter( function( el ) {
  return !toRemove.includes( el );
} );

下一个使用箭头函数的调整:

myArray = myArray.filter( ( el ) => !toRemove.includes( el ) );

其他回答

如果你不能使用新的ES5的东西这样的过滤器,我认为你被困在两个循环:

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

Lodash也有一个效用函数: https://lodash.com/docs#difference

过滤方法应该做到这一点:

const myArray = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
const toRemove = ['b', 'c', 'g'];

// ES5 syntax
const filteredArray = myArray.filter(function(x) { 
  return toRemove.indexOf(x) < 0;
});

如果toRemove数组很大,这种查找模式可能效率很低。创建一个映射,使查找是O(1)而不是O(n),这样会更有性能。

const toRemoveMap = toRemove.reduce(
  function(memo, item) {
    memo[item] = memo[item] || true;
    return memo;
  },
  {} // initialize an empty object
);

const filteredArray = myArray.filter(function (x) {
  return toRemoveMap[x];
});

// or, if you want to use ES6-style arrow syntax:
const toRemoveMap = toRemove.reduce((memo, item) => ({
  ...memo,
  [item]: true
}), {});

const filteredArray = myArray.filter(x => toRemoveMap[x]);

我只是实现为:

Array.prototype.exclude = function(list){
        return this.filter(function(el){return list.indexOf(el)<0;})
}

使用:

myArray.exclude(toRemove);
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'}
];



myArray = myArray.filter(ar => !toRemove.find(rm => (rm.name === ar.name && ar.place === rm.place) ))