Reputation: 59
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
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
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
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
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
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
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