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

Tap*_*Tap 185 javascript arrays jquery

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

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

// and this one:
var toRemove = ['b', 'c', 'g'];
Run Code Online (Sandbox Code Playgroud)

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

使用jQuery,我使用的是grep()inArray(),效果很好:

myArray = $.grep(myArray, function(value) {
    return $.inArray(value, toRemove) < 0;
});
Run Code Online (Sandbox Code Playgroud)

有没有一个纯粹的JavaScript方式来做到这一点没有循环和拼接?

Sir*_*rko 318

使用Array.filter()方法:

myArray = myArray.filter( function( el ) {
  return toRemove.indexOf( el ) < 0;
} );
Run Code Online (Sandbox Code Playgroud)

随着浏览器支持的Array.includes()增加,小改进:

myArray = myArray.filter( function( el ) {
  return !toRemove.includes( el );
} );
Run Code Online (Sandbox Code Playgroud)

使用箭头功能的下一个适应:

myArray = myArray.filter( ( el ) => !toRemove.includes( el ) );
Run Code Online (Sandbox Code Playgroud)

  • OP:如果你正在使用[Underscore.js](http://underscorejs.org/),那么[`.difference()`](http://underscorejs.org/#difference)基本上就是这样做的. (21认同)
  • 这个顺序不是n^2吗? (4认同)
  • 或更短:`myArray = myArray.filter(el =>!toRemove.includes(el));` (3认同)
  • 有没有办法按 n 的顺序实现这一点? (2认同)

Ash*_*han 29

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;
});
Run Code Online (Sandbox Code Playgroud)

如果您的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]);
Run Code Online (Sandbox Code Playgroud)


小智 29

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) ))
Run Code Online (Sandbox Code Playgroud)


Dee*_*rya 21

如果您正在使用对象数组.然后下面的代码应该做魔术,其中对象属性将是删除重复项的标准.

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

试试这个例子.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));
Run Code Online (Sandbox Code Playgroud)


Egg*_*gon 12

最简单的怎么样:

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

var myArray = myArray.filter((item) => !toRemove.includes(item));
console.log(myArray)
Run Code Online (Sandbox Code Playgroud)

  • 请记住,“includes”在 ES7 之前不可用。 (2认同)

小智 10

Lodash还有一个实用功能:https://lodash.com/docs#difference


Ben*_*uer 9

ECMAScript 6集可用于计算两个数组的不同元素:

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

const difference = new Set([...myArray].filter((x) => !toRemove.has(x)));

console.log(Array.from(difference)); // ["a", "d", "e", "f"]
Run Code Online (Sandbox Code Playgroud)

  • 与使用带有“.includes”的数组相比,这非常快。对于大型数组(~50,000),它从大约 79 秒缩短到不到 1 秒。感谢您发帖。 (7认同)
  • 很好的答案。我完全忘记了这件事 (2认同)

小智 8

您可以使用lodash 中的_.differenceBy

const myArray = [
  {name: 'deepak', place: 'bangalore'}, 
  {name: 'chirag', place: 'bangalore'}, 
  {name: 'alok', place: 'berhampur'}, 
  {name: 'chandan', place: 'mumbai'}
];
const toRemove = [
  {name: 'deepak', place: 'bangalore'},
  {name: 'alok', place: 'berhampur'}
];
const sorted = _.differenceBy(myArray, toRemove, 'name');
Run Code Online (Sandbox Code Playgroud)

示例代码在这里:CodePen


小智 7

我刚刚实现了:

Array.prototype.exclude = function(list){
        return this.filter(function(el){return list.indexOf(el)<0;})
}
Run Code Online (Sandbox Code Playgroud)

用于:

myArray.exclude(toRemove);
Run Code Online (Sandbox Code Playgroud)

  • 扩展原生对象的“原型”不是一个好习惯,比如“数组”。这可能会与语言的未来发展产生长期冲突([参见 `flatten` 案例](https://github.com/tc39/proposal-flatMap/pull/56)) (2认同)

Mar*_*coL 6

如果您不能使用新的ES5,filter我认为您遇到了两个循环:

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);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)


Mat*_*ius 6

现在是单线口味:

console.log(['a', 'b', 'c', 'd', 'e', 'f', 'g'].filter(x => !~['b', 'c', 'g'].indexOf(x)))
Run Code Online (Sandbox Code Playgroud)

可能不适用于旧浏览器。


Gop*_*hra 6

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

let df = [ {'name': 'C' },{'name': 'D' }] 
let nfl = [ {'name': 'A' },{'name': 'B' },{'name': 'C' },{'name': 'D' }] 
let res = nfl.filter(x => df.indexOf(x)<0)
console.log(res)
Run Code Online (Sandbox Code Playgroud)

这是工作代码:

let df = [{'name': 'C' },{'name': 'D' }]
let nfl = [ {'name': 'A' },{'name': 'B' },{'name': 'C' },{'name': 'D' }];
let res = nfl.filter((o1) => !df.some((o2) => o1.name === o2.name));
console.log(res)
Run Code Online (Sandbox Code Playgroud)