Javascript arrays: delete all elements contained in another array

I am looking for an efficient way to remove all elements from a javascript array if they are present in another array.

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

I want to work with myArray to leave it in this state: ['a', 'd', 'e', 'f']

With jQuery, I use grep() and inArray() , which works well:

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

Is there a pure javascript way to do this without looping and splicing?

+175
javascript jquery arrays
Nov 13 '13 at 15:13
source share
13 answers

Use the Array.filter() method:

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



A slight improvement as browser support for Array.includes() has increased:

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



The following adaptation using arrow functions :

 myArray = myArray.filter( ( el ) => !toRemove.includes( el ) ); 
+299
Nov 13 '13 at 15:16
source share

The filter method should do its job:

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

If your toRemove array toRemove large, this kind of search may be inefficient. It would be more productive to create a map so that the searches are O(1) and not 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]); 
+27
Nov 13 '13 at 15:17
source share

If you are using an array of objects. Then the code below should do the magic where the property of the object will be the criterion for removing duplicate elements.

In the example below, duplicates are removed by comparing the name of each item.

Try this example. 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)); 
+21
Jul 07 '15 at 12:18
source share

Lodash also has a utility function: https://lodash.com/docs#difference

+10
Oct 13 '15 at 9:03
source share

ECMAScript 6 sets can be used to calculate the various elements of two arrays:

 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"] 
+9
May 26 '17 at 14:35
source share

I just implemented as:

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

Use as:

 myArray.exclude(toRemove); 
+7
May 04 '16 at 9:57 a.m.
source share

If you can't use the new ES5 stuff, such a filter , I think you are stuck with two loops:

 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); } } } 
+6
Nov 13 '13 at 15:18
source share

Now in a single line taste:

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

Unable to work with older browsers.

+3
Jul 18 '16 at 14:22
source share

You can use _.differenceBy from lodash

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

Code example here: CodePen

+3
Mar 08 '18 at 11:41
source share
 var myArray = [ {name: 'deepak', place: 'bangalore'}, {name: 'chirag', place: 'bangalore'}, {name: 'alok', place: 'berhampur'}, {name: 'chandan', place: 'mumbai'}'enter code here' ]; var toRemove = [ {name: 'deepak', place: 'bangalore'}, {name: 'alok', place: 'berhampur'} ];'enter code here' myArray = myArray.filter(ar => !toRemove.find(rm => (rm.name === ar.name && ar.place === rm.place) )) 
+2
Apr 29 '19 at 9:45
source share

How about the simplest possible:

 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) 

+2
Aug 07 '19 at 15:14
source share

The correct way to delete all elements contained in another array is to make the original array the same object, deleting only the elements:

 Array.prototype.removeContained = function(array) { var i, results; i = this.length; results = []; while (i--) { if (array.indexOf(this[i]) !== -1) { results.push(this.splice(i, 1)); } } return results; }; 

Or the equivalent of CoffeeScript:

 Array.prototype.removeContained = (array) -> i = @length @splice i, 1 while i-- when array.indexOf(@[i]) isnt -1 

Testing inside Chrome Dev Tools:

19: 33: 04.447 a = 1
19: 33: 06.354 b = 2
19: 33: 07.615 s = 3
19: 33: 09.981 arr. = [A, b, c]
19: 33: 16.460 arr1 = arr

19: 33: 20.317 arr1 === arr
19: 33: 20,331 true

19: 33: 43.592 arr.removeContained ([a, c])
19: 33: 52.433 arr === arr1
19: 33: 52,438 true

Using the Angular Framework is the best way to keep a pointer to the source object when updating collections without a lot of watchers and reboots.

0
Jul 02 '18 at 12:45
source share

I am building logic without using any built-in methods, please let me know about optimizations or modifications. I tested in the JS editor, it works fine.

 var myArray = [ {name: 'deepak', place: 'bangalore'}, {name: 'alok', place: 'berhampur'}, {name: 'chirag', place: 'bangalore'}, {name: 'chandan', place: 'mumbai'}, ]; var toRemove = [ {name: 'chirag', place: 'bangalore'}, {name: 'deepak', place: 'bangalore'}, /*{name: 'chandan', place: 'mumbai'},*/ /*{name: 'alok', place: 'berhampur'},*/ ]; var tempArr = []; for( var i=0 ; i < myArray.length; i++){ for( var j=0; j<toRemove.length; j++){ var toRemoveObj = toRemove[j]; if(myArray[i] && (myArray[i].name === toRemove[j].name)) { break; }else if(myArray[i] && (myArray[i].name !== toRemove[j].name)){ var fnd = isExists(tempArr,myArray[i]); if(!fnd){ var idx = getIdex(toRemove,myArray[i]) if (idx === -1){ tempArr.push(myArray[i]); } } } } } function isExists(source,item){ var isFound = false; for( var i=0 ; i < source.length; i++){ var obj = source[i]; if(item && obj && obj.name === item.name){ isFound = true; break; } } return isFound; } function getIdex(toRemove,item){ var idex = -1; for( var i=0 ; i < toRemove.length; i++){ var rObj =toRemove[i]; if(rObj && item && rObj.name === item.name){ idex=i; break; } } return idex; } 
0
Jul 28 '18 at 22:12
source share



All Articles