Suppose I have this dataset:
const data = [ {animal: 'cat', name: 'mu', year: 2016}, {animal: 'cat', name: 'muji', year: 2021}, {animal: 'cat', name: 'mine', year: 2021}, {animal: 'dog', name: 'fido', year: 2000}, {animal: 'hamster', name: 'gerry', year: 2020}, {animal: 't-rex', name: 'dino', year: 2020}, {animal: 'sheep', name: 's', year: 2019}, {animal: 'sheep', name: 'sss', year: 2016}, ]
and I want to filter it by some values, for example by animal
and by year
. Very easy I can do:
const animal = 'sheep' const year = 2019 const filteredData = data.filter(d => d.animal === animal && d.year === year) // result const filteredData = [ {animal: 'sheep', name: 's', year: 2019}, ]
same here:
const animal = 'cat' const year = 2021 const filteredData = [ {animal: 'cat', name: 'muji', year: 2021}, {animal: 'cat', name: 'mine', year: 2021}, ]
My problem is that sometimes animal
or year
can be null
. In that case I want not to filter by that value. For example these are what I would like to obtain:
const animal = 'cat' const year = null const filteredData = [ {animal: 'cat', name: 'mu', year: 2016}, {animal: 'cat', name: 'muji', year: 2021}, {animal: 'cat', name: 'mine', year: 2021}, ] // --- const animal = null const year = 2020 const filteredData = [ {animal: 'hamster', name: 'gerry', year: 2020}, {animal: 't-rex', name: 'dino', year: 2020}, ] // --- const animal = null const year = null const filteredData = [ {animal: 'cat', name: 'mu', year: 2016}, {animal: 'cat', name: 'muji', year: 2021}, {animal: 'cat', name: 'mine', year: 2021}, {animal: 'dog', name: 'fido', year: 2000}, {animal: 'hamster', name: 'gerry', year: 2020}, {animal: 't-rex', name: 'dino', year: 2020}, {animal: 'sheep', name: 's', year: 2019}, {animal: 'sheep', name: 'sss', year: 2016}, ]
How can I do that?
Note that this is only a simple example, in my case I could have more than two variables as filters.
Advertisement
Answer
As you have written “I could have more than two variables as filters…“, I don’t think it is a good idea to hard-code filter expressions. Moreover, if both your data and filter are dynamic (if properties are not known beforehand) it is not even possible. Instead, you can use some approach like this:
const data = [ { animal: 'cat', name: 'mu', year: 2016 }, { animal: 'cat', name: 'muji', year: 2021 }, { animal: 'cat', name: 'mine', year: 2021 }, { animal: 'dog', name: 'fido', year: 2000 }, { animal: 'hamster', name: 'gerry', year: 2020 }, { animal: 't-rex', name: 'dino', year: 2020 }, { animal: 'sheep', name: 's', year: 2019 }, { animal: 'sheep', name: 'sss', year: 2016 } ]; const query = { animal: 'cat', year: null }; // remove all null values // https://stackoverflow.com/a/38340730 const q = Object.fromEntries(Object.entries(query).filter(([_, v]) => v != null)); // https://stackoverflow.com/a/61676007 const isSubset = (superObj, subObj) => { return Object.keys(subObj).every(ele => { if (typeof subObj[ele] == 'object') return isSubset(superObj[ele], subObj[ele]); return subObj[ele] === superObj[ele]; }); }; const filteredData = data.filter(d => isSubset(d, q)); console.log(filteredData);