0

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.

1
  • 1
    menuIten.filter(el => Object.keys(el).filter(i => (typeof i === "boolean").every(i => !i)); Commented Apr 22, 2022 at 1:20

2 Answers 2

2

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

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

2 Comments

Unfortunately, your code seems to have the same problem as my original example with multiple allergen values. If you add one more dish to your example and filter them with multiple allergen values, it will only filter the first allergen in the array correctly. –
Using .some instead of .every did the trick
2

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

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.