7

I've found a lot of posts that solve this problem:

Assuming we have:

array1 = ['A', 'B', 'C', 'D', 'E']; array2 = ['C', 'E'];

Is there a proven and fast solution to compare two arrays against each other, returning one array without the values appearing in both arrays (C and E here). Desired solution:

array3 = ['A', 'B', 'D']

But what if you have:

array1 = ['A', 'B', 'C', 'D', 'D', 'E']; array2 = ['D', 'E'];

and you're looking for the solution to be:

array3 = ['A', 'B', 'C', 'D'] // don't wipe out both D's

Here is some context:

You are trying to teach students about how sentences work. You give them a scrambled sentence:

ate -- cat -- mouse -- the -- the

They start typing an answer: The cat

You would like the prompt to now read:

ate -- mouse - the

At present, my code takes out both the's.

Here is what I've tried:
(zsentence is a copy of xsentence that will get manipulated by the code below, join()ed and put to screen)

for (i=0; i < answer_split.length; i++) {
for (j=0; j < xsentence.length; j++) {
        (function(){
            if (answer_split[i] == xsentence[j]) { zsentence.splice(j,1); return; }
        })();
    }
}
Brad Thomas
  • 103
  • 1
  • 1
  • 4
  • 2
    What's with the anonymous function and the return statement? As far as I can tell, neither of these does anything. – John Kugelman Jan 25 '13 at 04:33
  • @JohnKugelman the anonymous function is a self-invoking one, so it does _something._ The `return`, OTOH, is useless. – Matt Ball Jan 25 '13 at 04:39
  • @MattBall I mean why wrap the `if` statement in an anonymous function. It doesn't add anything. – John Kugelman Jan 25 '13 at 04:41
  • In this case - that's true. I'm guessing it's a misapplication of [this pattern](http://stackoverflow.com/q/750486/139010). – Matt Ball Jan 25 '13 at 04:43

2 Answers2

16

Just iterate over the array of elements you want to remove.

var array1 = ['A', 'B', 'C', 'D', 'D', 'E'];
var array2 = ['D', 'E'];
var index;

for (var i=0; i<array2.length; i++) {
    index = array1.indexOf(array2[i]);
    if (index > -1) {
        array1.splice(index, 1);
    }
}

It's O(array1.length * array2.length) but for reasonably small arrays and on modern hardware this shouldn't remotely cause an issue.

http://jsfiddle.net/mattball/puz7q/

https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/splice

Matt Ball
  • 354,903
  • 100
  • 647
  • 710
  • 1
    This is good. Your sample arrays are sorted. If this is the case, you can use a binary search to speed it up. http://en.wikipedia.org/wiki/Binary_search#Deferred_detection_of_equality "if the keys are not unique, it returns the smallest index" – brianchirls Jan 25 '13 at 08:04
  • Thanks Matt. That .indexOf section is exactly what I was looking for. – Brad Thomas Jan 25 '13 at 20:14
  • In this solution, you wouldn't be able to determine the cases when array2 is longer or contains 'F' and 'G' for example. – badunk Nov 18 '13 at 00:55
  • oops, I was taking the problem in a general sense of diffing 2 arrays - I suppose in this context you'll always have one array be a subset of another – badunk Nov 18 '13 at 01:04
  • @badunk regardless, the case you mentioned does not cause problems. Why do you think it might? http://jsfiddle.net/mattball/3zp66/ – Matt Ball Nov 18 '13 at 01:06
  • @MattBall sorry, misread the question originally and thought it applied to my own situation where I wanted to diff [a, b, c, d] and [c, b, e, f] to return [a], [b, c], and [e, f]. – badunk Nov 18 '13 at 01:29
8

You can use Filter also. Please review below example.

var item = [2,3,4,5];
var oldItems = [2,3,6,8,9];
oldItems = oldItems.filter(n=>!item.includes(n))

so this will return [6,8,9]

and if you want to get only matched items then you have to write below code.

oldItems = oldItems.filter(n=>item.includes(n))

This will return [2,3] only.

Ashish Bhanderi
  • 507
  • 1
  • 6
  • 21
  • 2
    I would recommend oldItems.filter(n => item.includes(n)); This is preferable to the accepted answer imo. No mutation and much cleaner code. – milesaron Feb 21 '19 at 23:06
  • Thanks @milesaron! – Ashish Bhanderi Aug 03 '19 at 06:26
  • var array1 = [1,-7,8,0,9]; var array2 = [0,-15,-7,1,8,9]; var oldItems = array1.filter(n=>!array2.includes(n));//output: [] var oldItems = array2.filter(n=>!array1.includes(n));//output: [-15] could you please write a code that solves 2 cases – bhaRATh Mar 16 '21 at 09:59