我正在寻找一种有效的方法,从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的方法来做到这一点没有循环和剪接?


当前回答

如果你正在使用Typescript并且想要匹配单个属性值,这应该基于上面Craciun Ciprian的答案。

您还可以通过允许非对象匹配和/或多属性值匹配使其更通用。

/**
 *
 * @param arr1 The initial array
 * @param arr2 The array to remove
 * @param propertyName the key of the object to match on
 */
function differenceByPropVal<T>(arr1: T[], arr2: T[], propertyName: string): T[] {
  return arr1.filter(
    (a: T): boolean =>
      !arr2.find((b: T): boolean => b[propertyName] === a[propertyName])
  );
}

其他回答

使用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 ) );

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

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

这已经很晚了,但添加这个来解释@mojtaba roohi的回答。第一个代码块将不起作用,因为每个数组都有不同的对象,即df[0] != nfl[2]。这两个对象看起来相似,但完全不同,当我们使用像数字这样的基本类型时,情况就不是这样了。

let df = [{'name': 'C'},{'name': 'D'}] 让nfl =[{'名字':' A '},{'名字':' B '},{'名字':' C '},{'名字':' D '}) Let res = nfl。filter(x => df.indexOf(x)<0) console.log (res)

下面是工作代码:

let df = [{'name': 'C'},{'name': 'D'}] 让nfl =[{'名字':' A '},{'名字':' B '},{'名字':' C '},{'名字':' D '}); 让res = nfl.filter ((o1群)= > ! df.some ((o2) = > o1.name = = = o2.name)); console.log (res)

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

如果你正在使用Typescript并且想要匹配单个属性值,这应该基于上面Craciun Ciprian的答案。

您还可以通过允许非对象匹配和/或多属性值匹配使其更通用。

/**
 *
 * @param arr1 The initial array
 * @param arr2 The array to remove
 * @param propertyName the key of the object to match on
 */
function differenceByPropVal<T>(arr1: T[], arr2: T[], propertyName: string): T[] {
  return arr1.filter(
    (a: T): boolean =>
      !arr2.find((b: T): boolean => b[propertyName] === a[propertyName])
  );
}