删除另一个数组中包含的所有元素

IT技术 javascript arrays
2021-02-02 04:57:28

我正在寻找一种有效的方法来从 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()and inArray(),效果很好:

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

有没有一种纯 javascript 的方式来做到这一点而无需循环和拼接?

6个回答

使用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 ) );
这个顺序不是n^2吗?
2021-03-13 04:57:28
OP:如果你使用Underscore.js.difference()它基本上就是这样做的。
2021-03-15 04:57:28
@AlecRust 将 的所有元素转换toRemove()为大写,并将回调中的更改从elel.toUpperCase()
2021-03-22 04:57:28
或更短: myArray = myArray.filter( el => !toRemove.includes( el ) );
2021-04-03 04:57:28
有没有办法按 n 的顺序实现这一目标?
2021-04-08 04:57:28

ECMAScript 6 集合可以允许更快地计算一个数组中不在另一个数组中的元素:

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

const difference = myArray.filter( x => !toRemove.has(x) );

console.log(difference); // ["a", "d", "e", "f"]

由于目前浏览器使用的 V8 引擎查找复杂度为 O(1),因此整个算法的时间复杂度为 O(n)。

很好的答案。我完全忘记了这个
2021-04-07 04:57:28
与使用 Array 和.includes. 对于大型阵列(~50,000),它从大约 79 秒变为不到 1 秒。感谢发布。
2021-04-09 04:57:28

filter方法应该可以解决问题:

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]);
我真的很喜欢这个答案......我只是要指出最后一行应该返回 const filtersArray = myArray.filter(x => !toRemoveMap[x]); // 而不是 toRemoveMap[x]
2021-03-23 04:57:28
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) ))
这对于具有唯一属性的对象数组很有用。+1
2021-03-13 04:57:28
你介意对这么受欢迎的问题做一些解释吗?
2021-03-16 04:57:28
我搜索了几个小时来解决问题并找到了它,太棒了。非常感谢你!
2021-03-21 04:57:28
你帮我在 1 天内完成了我的 jira 谢谢哥们
2021-03-26 04:57:28

如果您使用的是对象数组。那么下面的代码应该可以发挥作用,其中对象属性将是删除重复项的标准。

在下面的示例中,已删除重复项比较每个项目的名称。

试试这个例子。http://jsfiddle.net/deepak7641/zLj133rh/

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