4

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).

2
  • Change .includes() to .indexOf() != -1 Commented Jan 30, 2020 at 11:30
  • Also, you might want .some() instead of .every() Commented Jan 30, 2020 at 11:31

2 Answers 2

1

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)

Sign up to request clarification or add additional context in comments.

Comments

0

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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.