Reputation: 172
While coding a filter feature for my React.js app, I faced the problem below:
Since I have three different types of filters (date, campus, and city) I have to return to the user an array of objects based only on the filters that the user filled (it can be only one, two, or three of them). To solve this problem, I came up with this solution:
// Example of user input, something how my state variables should look
const date = null
const campus = "Example 1"
const city = "City 1"
//
const array = [ { date: "2020-11-23", campus: "Example 1", city: "City 1" },
{ date: "2020-11-24", campus: "Example 2", city: "City 2" }, ]
const filteredArray = array.filter(e => {
if (date && campus && city)
return e.date === date && e.campus === campus && e.city === city;
if (date && campus)
return e.date === date && e.campus === campus;
if (campus && city)
return e.campus === campus && e.city === city;
if (date && city)
return e.date === date && e.city === city;
if (date)
return e.date === date;
if (campus)
return e.campus === campus;
if (city)
return e.city === city;
});
Well, is there any other way to discard null values while returning the filtered objects, so I can reduce the size of my code?
Upvotes: 1
Views: 442
Reputation: 20734
you can combine them into a single statement:
const filteredArray = array.filter(e =>
(!date || date === e.date) && (!campus || campus === e.campus) && (!city || city === e.city)
);
Also, you can make an object to dynamically check all the conditions without rewriting every property again:
const conditions = {
date: null, // you can also remove this line
campus: 'Example 1',
city: 'City 1'
};
const array = [
{ date: '2020-11-23', campus: 'Example 1', city: 'City 1' },
{ date: '2020-11-24', campus: 'Example 2', city: 'City 2' }
];
const filteredArray = array.filter(e => Object.entries(conditions).every(([key, value]) => !value || e[key] === value));
console.log(filteredArray);
Upvotes: 5
Reputation: 345
A better way of doing this would be to run the filters individually and in series.
something like:
function filter(array, date, campus, city) {
let filteredByDate = filterBy(array, date, 'date')
let filteredByCampus = filterBy(filteredByDate, campus, 'campus')
let filteredByCity = filterBy(filteredByCampus, city, 'city')
return filteredByCity
}
then individual filters would look like this:
function filterBy(array, data, prop) {
if(!date) return array
else return array.filter(e => (e[prop] === data))
}
Upvotes: 2