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" }
];
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" }
];
Share
Improve this question
edited Jun 14, 2016 at 14:07
Andreas
21.9k7 gold badges51 silver badges58 bronze badges
asked Jun 14, 2016 at 13:58
user3667159user3667159
591 silver badge6 bronze badges
6 Answers
Reset to default 4You 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);
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));
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)
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./ajax/libs/lodash.js/4.13.1/lodash.min.js"></script>
to pare the objects inside some
method I'm using lodash isEqual
but you could use something else to test objects.
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.pare()
and Array.prototype.diference()
.
Object.prototype.pare = 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.pare(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));
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"
}
]