I have my array object in the following format
menuItem = [{
"name": "MOZZARELLA DI BUFALA & TOMATOES",
"gluten": true,
"eggs": false,
"dairy": true,
...
},...
I want to filter hundreds of menuItems by the allergen values (Boolean).
While the following code does the trick:
menuItem.filter(el => !el.gluten && !el.fish && !el.soy && !el.dairy)"
The allergens are hardcoded and repetitive. I am struggling to make the code dynamic and elegant.
I tried the following solution
menuItem.filter(el => !el[allergens])"
var allergens = ['gluten', 'fish', 'soy', 'dairy']
However, it only works correctly with one allergen value. Multiple values as in the above example do not filter anything.
First extract the name property, then check that the rest of the properties in the object are falsey.
menuItem.filter(
({ name, ...rest }) => Object.values(rest).every(val => !val)
);
Ideally, I'd prefer to restructure the input array so the allergies are in a separate property, perhaps:
menuItem = [{
"name": "MOZZARELLA DI BUFALA & TOMATOES",
allergens: {
"gluten": true,
"eggs": false,
"dairy": true,
to make accessing them easier.
menuItem.filter(
({ allergens }) => Object.values(allergens).every(val => !val)
);
You could use .some or .every, whichever match your case
const allergens = ['gluten', 'fish', 'soy', 'dairy']
const res = menuItem.filter(
(el) => !allergens.every((allergen) => el[allergen])
);
// equivalent to `menuItem.filter(el => !el.gluten && !el.fish && !el.soy && !el.dairy)`
const menuItem = [
{
name: 'dish A',
gluten: true,
fish: true,
soy: true,
dairy: true,
},
{
name: 'dish B',
gluten: true,
fish: true,
soy: false,
dairy: true,
},
];
const allergens = ['gluten', 'fish', 'soy', 'dairy'];
const res = menuItem.filter(
(el) => !allergens.every((allergen) => el[allergen])
);
console.log(res);