Reputation: 53
I am attempting to filter an array of objects using multiple different filters. This currently works for an exact match but doesn't work for filtering using a substring. Is there a way to simply modify this filter function to to return all values that have a partial match?
nestedFilter(data, filters) {
let filterKeys = Object.keys(filters);
return data.filter(function (eachObj) {
return filterKeys.every(function (eachKey) {
if (!filters[eachKey].length) {
return true;
}
return filters[eachKey].includes(eachObj[eachKey]);
});
});
}
So using the below data and filters:
data = [
{
"NAME": "Johnathon",
"AGE": "19 ",
"GENDER": "M",
"SPORT": "Hockey",
"SCHOLARSHIP": "N"
},
{
"NAME": "Jessica",
"AGE": "20",
"GENDER": "F",
"SPORT": "Football",
"SCHOLARSHIP": "Y"
},
{
"NAME": "Matty",
"AGE": "20",
"GENDER": "NB",
"SPORT": "Tennis",
"SCHOLARSHIP": "Y"
},
{
"NAME": "Amy",
"AGE": "20",
"GENDER": "F",
"SPORT": "Football",
"SCHOLARSHIP": "N"
}
]
filters = [
{
"NAME": [],
"AGE": [],
"GENDER": [],
"SPORT": ["Foot", "Hockey"],
"SCHOLARSHIP": []
}
]
It should return Johnathon, Jessica and Amy objects.
(Filters in different fields act as AND and filters in the same field act as OR).
Upvotes: 4
Views: 2183
Reputation: 8761
Using Array.reduce(), AND can be implemented in every iteration
Using Array.some(), OR can be implemented for each filter
Filter only if the array is not empty.
var data = [
{ "NAME": "Johnathon", "AGE": "19 ", "GENDER": "M", "SPORT": "Hockey", "SCHOLARSHIP": "N" },
{ "NAME": "Jessica", "AGE": "20", "GENDER": "F", "SPORT": "Football", "SCHOLARSHIP": "Y" },
{ "NAME": "Matty", "AGE": "20", "GENDER": "NB", "SPORT": "Tennis", "SCHOLARSHIP": "Y" },
{ "NAME": "Amy", "AGE": "20", "GENDER": "F", "SPORT": "Football", "SCHOLARSHIP": "N" }
];
var filters = {
"NAME": ["Amy"],
"AGE": [],
"GENDER": [],
"SPORT": ["Foot", "Hockey"],
"SCHOLARSHIP": ["Y","N"]
};
var filterkeys = Object.keys(filters);
var result = data.slice(0);
filterkeys.forEach(function(filterkey){
if(filters[filterkey].length)
{
result = result.reduce(function(acc, value){
filters[filterkey].some(function(filtervalue){
return value[filterkey].indexOf(filtervalue)>-1;
}) && acc.push(value);
return acc;
},[]);
}
});
console.log(result)
Upvotes: 0
Reputation: 12019
To employ a partial match for the object's property, you would want to check if the value contains at least one of the items in the list of filters. For example:
"Footbal".includes("Foot") || "Football".includes("Hockey") // true;
We can use Array.some to make this assertion:
return filters[eachKey].some(key => {
return eachObj[eachKey].includes(key);
});
A little correction:
The filters
variable is an array so you might want to either convert it to an object or run the nestedFilter
function with filters[0]
(referring to the first item in the array)
Upvotes: 1