4

I have 2 arrays as follows. I want to compare both arrays and only provide the elements from 'check' which are not present in 'data' array.

var check= ["044", "451"],
data = ["343", "333", "044", "123", "444", "555"];

The function used is as follows. This function will result in providing the elements in 'check' array which are present in 'data' array

function getMatch(a, b) {
var matches = [];

for ( var i = 0; i < a.length; i++ ) {
    for ( var e = 0; e < b.length; e++ ) {
        if ( a[i] === b[e] ) matches.push( a[i] );
    }
}
return matches;
}

getMatch(check, data); // ["044"] ---> this will be the answer as '044' is only present in 'data'

I want to have a list of elements which are not present in 'data' array. Can someone let me know how to achieve this.

Adu Rao
  • 101
  • 2
  • 4
  • 10

4 Answers4

18

You could use filter and Set, providing the Set as context to the filter method, so it can be accessed as this:

var check= ["044", "451"],
data = ["343", "333", "044", "123", "444", "555"];

var res = check.filter( function(n) { return !this.has(n) }, new Set(data) );

console.log(res);

Note that this runs in O(n) time, contrary to indexOf/includes based solutions, which really represent a nested loop.

trincot
  • 317,000
  • 35
  • 244
  • 286
  • this solution is helpful but what if i've array of objects to compare? can you provide solution for this scenario? – Prasanna Aug 16 '18 at 09:26
  • Sure, that is possible. Have a look at the answer [here](https://stackoverflow.com/a/47042484/5459839). – trincot Aug 16 '18 at 09:39
2

There is a lot of ways to achieve this, however I will keep your style of coding. Before nested loop set matches flag to false and set it to true in nested loop if match found, after nested loop check your flag if it is false then push element in missing array.

function getMissing(a, b) {
    var missings = [];
    var matches = false;

    for ( var i = 0; i < a.length; i++ ) {
        matches = false;
        for ( var e = 0; e < b.length; e++ ) {
            if ( a[i] === b[e] ) matches = true;
        }
        if(!matches) missings.push( a[i] );
    }
    return missings;
}
simon
  • 1,405
  • 1
  • 15
  • 24
1

You can use indexOf and filter for this:

check.filter((item) => { 
  return data.indexOf(item) === -1 
})
geekonaut
  • 5,714
  • 2
  • 28
  • 30
  • 1
    Fair enough, here without arrow function: check.filter(function(item) { return data.indexOf(item) === -1 }) Here with includes: check.filter((item) => { return !data.includes(item) }) ;-) – geekonaut Nov 10 '16 at 22:25
1

Edit

The .find() method, as mentioned in a comment, only returns a single value satisfying the predicate function it is given. To correct this, simply substitute .find() with the .filter() function and it should work as intended. Thanks for the catch.

If you're familiar with ES6, you can use the purpose-built .find() Array method; it is, afterall, provided for situations just like the one described. It takes a predicate function and returns the values from the array .find() was called on (here, check) that satisfy the predicate function argument. In my code, the predicate function simply checks for values that are not present in the data array. .includes() is likewise a product of the recent ES6 JavaScript specification and returns a Boolean.

var check= ["044", "451"],
data = ["343", "333", "044", "123", "444", "555"];

let notPresentInData = check.filter(val => !data.includes(val));
console.log(notPresentInData);
IsenrichO
  • 4,251
  • 3
  • 18
  • 31