Home > OS >  How to filter without using the filter method in javascript?
How to filter without using the filter method in javascript?

Time:05-10

I have to convert 2 functions, both using filter methods into something using for loops, how am i supposed to do that ? For some case, it makes sense, but using the push method is a bit confusing.

Thanks in advance

First function :

function filterWithInputValue(recipes) {
    filteredRecipes = recipes.filter(recipe => {
        const lowerCaseName = recipe.name.toLowerCase().includes(input.value.toLowerCase());
        const lowerCaseDescription = recipe.description.toLowerCase().includes(input.value.toLowerCase());
        const lowerCaseIngredients = recipe.ingredients.filter(({ ingredient }) => ingredient.toLowerCase().includes(input.value.toLowerCase())).length > 0
        return  lowerCaseIngredients | lowerCaseName | lowerCaseDescription;
    });
};

My current version of the function :

function filterWithInputValue(recipes) {
    for (let recipe of recipes) {
        const lowerCaseName = recipe.name.toLowerCase().includes(input.value.toLowerCase());
        const lowerCaseDescription = recipe.description.toLowerCase().includes(input.value.toLowerCase());
        
        for (let ingredient of recipe.ingredients) {
            //????
        }
        
        if (lowerCaseName | lowerCaseDescription | lowerCaseIngredient) {
            filteredRecipes.push(recipe)
        };
    };
};

Second function :

                if(tags.length >= 1) {
                    if(input.value.length >= 3) filterWithInputValue(recipes)
                    else filteredRecipes = recipes

                    const tagList = document.querySelectorAll(".tag");
                    
                    tagList.forEach((tag) => {
                        if(tag.classList.contains("tag0")) {
                            filteredRecipes = filteredRecipes.filter(recipe => recipe.ingredients.some(
                                ({ingredient}) => ingredient.includes(tag.innerText)))
                        }
                        if(tag.classList.contains("tag1")) filteredRecipes = filteredRecipes.filter(recipe => recipe.appliance.includes(tag.innerText))
                        if(tag.classList.contains("tag2")) filteredRecipes = filteredRecipes.filter(recipe => recipe.ustensils.includes(tag.innerText))
                    })
                    createRecipeCard(filteredRecipes)
                    mainInputFiltering(filteredRecipes)
                };

Example of a recipes/data :

{
        "id": 1,
        "name" : "Limonade de Coco",
        "servings" : 1,
        "ingredients": [
            {
                "ingredient" : "Lait de coco",
                "quantity" : 400,
                "unit" : "ml"
            },
            {
                "ingredient" : "Jus de citron",
                "quantity" : 2
            },
            {
                "ingredient" : "Crème de coco",
                "quantity" : 2,
                "unit" : "cuillères à soupe"
            },
            {
                "ingredient" : "Sucre",
                "quantity" : 30,
                "unit" : "grammes"
            },
            {
                "ingredient": "Glaçons"
            }
        ],
        "time": 10,
        "description": "Mettre les glaçons à votre goût dans le blender, ajouter le lait, la crème de coco, le jus de 2 citrons et le sucre. Mixer jusqu'à avoir la consistence désirée",
        "appliance": "Blender",
        "ustensils": ["cuillère à Soupe", "verres", "presse citron" ]
    }

CodePudding user response:

For a fairly straight forward conversion your first function could look like the following (not tested):

function filterWithInputValue(recipes) {
  let filteredRecipes = []; // create array to hold the results of filtering the recipes

  for (let recipe of recipes) {
    const lowerCaseName = recipe.name.toLowerCase().includes(input.value.toLowerCase());
    const lowerCaseDescription = recipe.description.toLowerCase().includes(input.value.toLowerCase());

    let filteredIngredients = []; // create array to hold the results of filtering the ingredients
    for (let { ingredient } of recipe.ingredients) {
      if(ingredient.toLowerCase().includes(input.value.toLowerCase())) {
        filteredIngredients.push(ingredient); // push those that succeed on the condition into the results array
      }
    }
    
    let lowerCaseIngredient = filteredIngredients.length > 0;

    if (lowerCaseName | lowerCaseDescription | lowerCaseIngredient) {
      filteredRecipes.push(recipe); // push those that succeed on the condition into the results array
    }
  }

  return filteredRecipes; // return the results of filtering
}

the general priciple here is that you can create an array to accumulate results, add things that succeed at the conditional (that you take from your filter method) to this array and then return the array.

A slightly cleaner version of the above could look like:

function filterIngredients(ingredients, lowercaseInput) {
  let filteredIngredients = []; // create array to hold the results of filtering the ingredients
  for (let { ingredient } of ingredients) {
    if(ingredient.toLowerCase().includes(lowercaseInput)) {
      filteredIngredients.push(ingredient); // push those that succeed on the condition into the results array
    }
  }
  return filteredIngredients;
}

function filterWithInputValue(recipes) {
  let lowercaseInput = input.value.toLowerCase();
  let filteredRecipes = []; // create array to hold the results of filtering the recipes

  for (let recipe of recipes) {
    const lowerCaseName = recipe.name.toLowerCase().includes(lowercaseInput);
    const lowerCaseDescription = recipe.description.toLowerCase().includes(lowercaseInput);

    const lowerCaseIngredient = filteredIngredients(recipe.ingredients, lowercaseInput).length > 0;

    if (lowerCaseName | lowerCaseDescription | lowerCaseIngredient) {
      filteredRecipes.push(recipe); // push those that succeed on the condition into the results array
    }
  }

  return filteredRecipes; // return the results of filtering
}

where you can probably see that the filtering of the ingredients is following the same general pattern as the filtering of the recipes.

A couple of notes:

  1. It looks like the filter on the ingredients could actually be a some instead as it looks like ingedients are just being checked for any matches and doesn't care about the number or details of them.
  2. The original filterWithInputValue does not actually return anything so I'm wondering how it gets used / checked.
  • Related