user3667159
user3667159

Reputation: 59

Filter array with another array with jQuery or JavaScript

I am trying to filter an array 'arrSOPrecods' with key values from 'outputdata' another array. the first array 'arrSOPrecods' contains records for users to be trained for a specific SOP the second array 'outputdata' contains records for users already trained for specific SOP I will need to filter out the records that exist in outputdata from arrSOprecords. I have tried many different methods such as jQuery filter, JavaScript for loop as well as its own .filter function with little progress but nothing useful. here is example of the data and what the final output should be.

var arrSOPrecords = [
    { User: "Cesar", SOP: "training 1" },
    { User: "Cesar", SOP: "training 2" },
    { User: "Jon", SOP: "training 1" },
    { User: "Jon", SOP: "training 2" },
    { User: "Ana", SOP: "training 1" },
    { User: "Ana", SOP: "training 2" }
];

var outputdata = [
    { User: "Cesar", SOP: "training 1" }, 
    { User: "Cesar", SOP: "training 2" }, 
    { User: "Ana", SOP: "training 1" }, 
    { User: "Jon", SOP: "training 1" }
];

the final output array .

var filtered = [
    { User: "Ana", SOP: "training 2" },
    { User: "Jon", SOP: "training 2" }
];

Upvotes: 3

Views: 2577

Answers (6)

RomanPerekhrest
RomanPerekhrest

Reputation: 92854

Here is simple solution using Array.filter and Array.indexOf functions:

var filtered = [], trained = {};

outputdata.forEach(function(o) {
    trained[o.User] = trained[o.User] || [];
    trained[o.User].push(o.SOP);
});
filtered = arrSOPrecords.filter(function(o) {
    return !trained[o.User] || trained[o.User].indexOf(o.SOP) === -1;
});

console.log(JSON.stringify(filtered, 0 , 4)); 

The output:

[
    {
        "User": "Jon",
        "SOP": "training 2"
    },
    {
        "User": "Ana",
        "SOP": "training 2"
    }
]

Upvotes: 0

Nenad Vracar
Nenad Vracar

Reputation: 122037

You could use map() on both arrays and return string of User + SOP and then use indexOf() to filter

var arrSOPrecords=[{User:"Cesar", SOP:"training 1"},{User:"Cesar", SOP:"training 2"},{User:"Jon", SOP:"training 1"},{User:"Jon", SOP:"training 2"},{User:"Ana", SOP:"training 1"},{User:"Ana", SOP:"training 2"}]; 
var outputdata= [{User:"Cesar", SOP:"training 1"},{User:"Cesar", SOP:"training 2"},{User:"Ana", SOP:"training 1"},{User:"Jon", SOP:"training 1"}]

var a = arrSOPrecords.map(e => e.User+e.SOP);
var b = outputdata.map(e => e.User+e.SOP);

var result = arrSOPrecords.filter(function(e, i) {
  return b.indexOf(a[i]) == -1;
});

console.log(result)

Update: You can actually just use map on second array and then use filter like this

var arrSOPrecords = [{ User: "Cesar", SOP: "training 1" }, { User: "Cesar", SOP: "training 2" }, { User: "Jon", SOP: "training 1" }, { User: "Jon", SOP: "training 2" }, { User: "Ana", SOP: "training 1" }, { User: "Ana", SOP: "training 2" }];
var outputdata = [{ User: "Cesar", SOP: "training 1" }, { User: "Cesar", SOP: "training 2" }, { User: "Ana", SOP: "training 1" }, { User: "Jon", SOP: "training 1" }];

var a = outputdata.map(e => e.User+e.SOP);
var result = arrSOPrecords.filter(function(el) {
  return a.indexOf(el.User+el.SOP) == -1;
})

console.log(result)

Upvotes: 1

Redu
Redu

Reputation: 26161

I like to present generic, reusable solutions for these problems. The following code will list the objects those are present in array that's called upon which are missing in the array that is provided as an argument. We are utilizing two generic methods; Object.prototype.compare() and Array.prototype.diference().

Object.prototype.compare = function(o){
  var ok = Object.keys(this);
  return typeof o === "object" && ok.length === Object.keys(o).length ? ok.every(k => this[k] === o[k]) : false;
};
Array.prototype.difference = function(a) {
  return this.filter(e => !a.some(f => f.compare(e)));
};
var arrSOP = [
    { User: "Cesar", SOP: "training 1" },
    { User: "Cesar", SOP: "training 2" },
    { User: "Jon", SOP: "training 1" },
    { User: "Jon", SOP: "training 2" },
    { User: "Ana", SOP: "training 1" },
    { User: "Ana", SOP: "training 2" }
],
   outData = [
    { User: "Cesar", SOP: "training 1" }, 
    { User: "Cesar", SOP: "training 2" }, 
    { User: "Ana", SOP: "training 1" }, 
    { User: "Jon", SOP: "training 1" }
],
  filtered = arrSOP.difference(outData);
console.log(JSON.stringify(filtered));

Upvotes: 0

maioman
maioman

Reputation: 18734

you can try filtering the first array with array.some method:

var arrSOPrecords=[{User:"Cesar", SOP:"training 1"},{User:"Cesar", SOP:"training 2"},{User:"Jon", SOP:"training 1"},{User:"Jon", SOP:"training 2"},{User:"Ana", SOP:"training 1"},{User:"Ana", SOP:"training 2"}];
var outputdata= [{User:"Cesar", SOP:"training 1"},{User:"Cesar", SOP:"training 2"},{User:"Ana", SOP:"training 1"},{User:"Jon", SOP:"training 1"}]


var r = arrSOPrecords.filter(x => !outputdata.some(y => _.isEqual(y,x)))

console.log(r)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.min.js"></script>

to compare the objects inside some method I'm using lodash isEqual but you could use something else to test objects.

Upvotes: 0

Andreas
Andreas

Reputation: 21881

Array.prototype.filter() + Array.prototype.some()

var arrSOPrecords = [
    { User: "Cesar", SOP: "training 1" },
    { User: "Cesar", SOP: "training 2" },
    { User: "Jon", SOP: "training 1" },
    { User: "Jon", SOP: "training 2" },
    { User: "Ana", SOP: "training 1" },
    { User: "Ana", SOP: "training 2" }
];

var outputdata = [
    { User: "Cesar", SOP: "training 1" }, 
    { User: "Cesar", SOP: "training 2" }, 
    { User: "Ana", SOP: "training 1" }, 
    { User: "Jon", SOP: "training 1" }
];

var filtered = arrSOPrecords.filter(function(r) {
    return !outputdata.some(function(t) {
        return r.User === t.User && r.SOP === t.SOP;
    });
});

console.log(JSON.stringify(filtered));

Upvotes: 1

Nina Scholz
Nina Scholz

Reputation: 386560

You could use a hash table for the items, you want to exclude and filter then the records.

var arrSOPrecords = [{ User: "Cesar", SOP: "training 1" }, { User: "Cesar", SOP: "training 2" }, { User: "Jon", SOP: "training 1" }, { User: "Jon", SOP: "training 2" }, { User: "Ana", SOP: "training 1" }, { User: "Ana", SOP: "training 2" }],
    outputdata = [{ User: "Cesar", SOP: "training 1" }, { User: "Cesar", SOP: "training 2" }, { User: "Ana", SOP: "training 1" }, { User: "Jon", SOP: "training 1" }],
    filtered,
    hash = Object.create(null);

outputdata.forEach(function (a) {
    hash[a.User + '|' + a.SOP] = true;
});
filtered = arrSOPrecords.filter(function (a) {
    return !hash[a.User + '|' + a.SOP];
});

console.log(filtered);

Upvotes: 4

Related Questions