30

Assume we have the following arrays:

a = [1, 2, 3, 4, 5]

and

b = [2, 3]

How can I subtract b from a? So that we have c = a - b which should be equal to [1, 4, 5]. jQuery solution would also be fine.

David Weng
  • 4,165
  • 12
  • 42
  • 51
  • Does this answer your question? [Remove all elements contained in another array](https://stackoverflow.com/questions/19957348/remove-all-elements-contained-in-another-array) – Heretic Monkey Jul 18 '22 at 11:58

6 Answers6

46

Assuming you're on a browser that has Array.prototype.filter and Array.prototype.indexOf, you could use this:

var c = a.filter(function(item) {
    return b.indexOf(item) === -1;
});

If the browser in question does not have those methods, you may be able to shim them.

icktoofay
  • 126,289
  • 21
  • 250
  • 231
11

This is a modified version of the answer posted by @icktoofay.

In ES6 we can make use of:

This will simplify our code to:

var c = a.filter(x => !b.includes(x));

Demo:

var a = [1, 2, 3, 4, 5];
var b = [2, 3];

var c = a.filter(x => !b.includes(x));
console.log(c);
Mohammad Usman
  • 37,952
  • 20
  • 92
  • 95
3

For code that would work in all browsers, you would have to manually find each element from b in a and remove it.

var a = [1, 2, 3, 4, 5];
var b = [2, 3];

var result = [], found;
for (var i = 0; i < a.length; i++) {
    found = false;
    // find a[i] in b
    for (var j = 0; j < b.length; j++) {
        if (a[i] == b[j]) {
            found = true;
            break;
        }
    }
    if (!found) {
        result.push(a[i]);
    }
}
// The array result now contains just the items from a that are not in b

Working example here: http://jsfiddle.net/jfriend00/xkBzR/

And, here's a version that could be faster for large arrays because it puts everything into an object for hashed lookups rather than brute force array searching:

var a = [1, 2, 3, 4, 5];
var b = [2, 3];

function filterArray(src, filt) {
    var temp = {}, i, result = [];
    // load contents of filt into object keys for faster lookup
    for (i = 0; i < filt.length; i++) {
        temp[filt[i]] = true;
    }

    // go through src
    for (i = 0; i < src.length; i++) {
        if (!(src[i] in temp)) {
            result.push(src[i]);
        }
    }
    return(result);
}

var filtered = filterArray(a, b);

Working example here: http://jsfiddle.net/jfriend00/LUcx6/

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • why do not implement `Array.filter` method? may be useful in other cases too. – Kakashi Oct 06 '11 at 01:52
  • `Array.filter()` is useful - I'm just providing an alternative. Some people don't want to add methods to existing core objects or they have code that might break if that was done. – jfriend00 Oct 06 '11 at 02:00
2

For the ones struggling with Objects, like Date, you'll find out that two different objects are never equal to each other, even if they have the same values, so the answers above wouldn't work. Here is an answer to this problem in ES6.

const c = a.filter(aObject => b.findIndex(bObject => aObject.valueOf() === bObject.valueOf()) === -1)
Nati Lara-Diaz
  • 2,056
  • 16
  • 8
0

Might be an outdated query but i thought this might be useful to someone.

let first = [1,2,3,4,5,6,7,9];
let second = [2,4,6,8];
const difference = first.filter(item=>!second.includes(item));
console.log(difference);//[ 1, 3, 6,7]
/*
the above will not work for objects with properties
This might do the trick
*/
const firstObj = [{a:1,b:2},{a:3,b:4},{a:5,b:6},{a:7,b:8}]//not ideal. I know
const secondObj = [{a:3,b:4},{a:7,b:8}]

const objDiff = firstObj.filter(obj=>
  !secondObj.find(sec=>//take note of the "!"
    sec.a===obj.a
    &&//or use || if you want to check for either or
    sec.b===obj.b
  )//this is formatted so that it is easily readable
);
console.log(objDiff)/*
[
  {
    "a": 1,
    "b": 2
  },
  {
    "a": 5,
    "b": 6
  }
]
*/
0

Here an implementation for try works in all browsers:

if('filter' in Array == false) {
    Array.prototype.filter = 
        function(callback) {
            if(null == this || void 0 == this) {
                return;
             }
            var filtered = [];
            for(i = 0, len = this.length; i < len; i++) {
                    var tmp = this[i];
                    if(callback(tmp)) {
                        filtered.push(tmp);
                     }
             }
                return filtered;
       }
  }

a = [1, 2, 3, 4, 5]; 
b = [2, 3]; 

var c = a.filter(function(item) { /*implementation of icktoofay */
    return b.indexOf(item) === -1;
});
Kakashi
  • 2,165
  • 14
  • 19
  • Array.indexOf does not exist in all browsers either (not in any version of IE before IE9, for example.) – jfriend00 Oct 06 '11 at 02:25