1

The chooseRecipe function should compare the arrays in bakeryA and bakeryB with the ingredients of each recipe. If bakeryA and bakeryB each have an ingredient for a recipe, then the name of the recipe should be printed. In this case, Persian Cheesecake is what should be printed. However, it keeps returning an empty array.

I understand that I'm starting off with an empty array, but shouldn't suitableRecipe.push(recipes[i].name); be taking care of that?

Would appreciate any guidance, or suggestions for a better way to do this.

let bakeryA = ['saffron', 'eggs', 'tomato paste', 'coconut', 'custard'];
let bakeryB = ['milk', 'butter', 'cream cheese'];
let recipes = [
    {
        name: 'Coconut Sponge Cake',
        ingredients: ['coconut', 'cake base']
    },
    {
        name: 'Persian Cheesecake',
        ingredients: ['saffron', 'cream cheese']
    },
    {
        name: 'Custard Surprise',
        ingredients: ['custard', 'ground beef']
    }
];

const chooseRecipe = function(bakeryA, bakeryB, recipes) {
  let suitableRecipe = [];
  for (let i = 0; i < recipes.length; i++) {
    for (let j = 0; j < recipes[i].ingredients.length; j++) {
      for (let k = 0; k < bakeryA.length; k++) {
        if (bakeryA[k] === recipes[i].ingredients[j]) {
          for (let l = 0; l < bakeryB.length; l++) {
            for (let m = 0; m < recipes[i].ingredients; m++) {
              if (bakeryB[l] === recipes[i].ingredients[m]) {
                suitableRecipe.push(recipes[i].name);
              }
            }
          }
        }
      }
    }
  }
  return suitableRecipe;
}

console.log(chooseRecipe(bakeryA, bakeryB, recipes));
2
  • 1
    for (let m = 0; m < recipes[i].ingredients; m++) { is missing .length for ingredients ? Commented Feb 21, 2021 at 22:45
  • That was it! Thank you so much! Can't believe I missed that! Commented Feb 21, 2021 at 22:52

2 Answers 2

2

There is a much cleaner way to do this, and it involves using Sets. Assuming that bakeryA and bakeryB list each ingredient once:

let bakeryA = ['saffron', 'eggs', 'tomato paste', 'coconut', 'custard'];
let bakeryB = ['milk', 'butter', 'cream cheese'];
let recipes = [
    {
        name: 'Coconut Sponge Cake',
        ingredients: ['coconut', 'cake base']
    },
    {
        name: 'Persian Cheesecake',
        ingredients: ['saffron', 'cream cheese']
    },
    {
        name: 'Custard Surprise',
        ingredients: ['custard', 'ground beef']
    }
];

const chooseRecipe = function(bakeryA, bakeryB, recipes) {
  let aIngredients = new Set(bakeryA);
  let bIngredients = new Set(bakeryB);
  return recipes.filter(recipe => 
     recipe.ingredients.every(ingredient =>
         aIngredients.has(ingredient) || bIngredients.has(ingredient))
  );
}

console.log(chooseRecipe(bakeryA, bakeryB, recipes));

Some notes:

  • Array.prototype.every allows you to check if every ingredient in a recipe is in either bakeryA or bakeryB.
  • Array.prototype.filter is used to iterate over and filter out values that don't match that condition specified.

This approach is also more efficient, since it saves you from having to loop 5 (!) times, which will get very very slow as bakeryA, bakeryB, ingredients and recipes become larger and larger.

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

Comments

1

I would advise you to use handy array functions like filter, find and some for that kind of opperation. However if you simply want to know why your code doesn't work, there's an easy fix.

You are missing a .length in your innermost for loop. The correct loop is:

for (let m = 0; m < recipes[i].ingredients.length; m++) {
...
}

You coud make it way more concise by using the available array functionality. A solution could look like:

const choose = (bakeryA, bakeryB, recipes) => recipes.filter(
    ({ingredients}) => bakeryA.some(i => ingredients.includes(i)) && bakeryB.some(i => ingredients.includes(i))
);

1 Comment

Thank you! The fact I missed the .length really illustrates why looping like this is not a great idea. I'll look into using the filter function for this.

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.