开发者问题收集

如何在检查输入值的同时过滤数组?

2022-04-18
491

我在尝试过滤数组时遇到问题(见下文),我尝试过滤食谱,同时检查某种成分是否在食谱中。

下面是我的问题的简单示例。 首先是 JSON

{"recipes": [
    {
        "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"
            }
        ]
    }]
}
<input class="input" />

    <script>
        const input = document.querySelector(".input")
        async function getRecipes() {
            const response = await (await fetch("./recipes.json")).json();
            const recipes = response.recipes;
            return ({ recipes: [...recipes] });
        };

        function filter(recipes) {
            input.addEventListener("input", () => {
                var filteredRecipes = recipes.filter(recipe => {
                    return recipe.ingredients.ingredient.toLowerCase().includes(input.value.toLowerCase())
                })
                console.log(filteredRecipes)
            })
        }

        async function init() {
            const { recipes } = await getRecipes();
            filter(recipes)
        }

        init()
    </script>

此错误出现在控制台中:

index.html:23 Uncaught TypeError: Cannot read properties of undefined (reading 'toLowerCase')

这完全没问题,因为每种成分都不是一种成分。我尝试对成分数组进行 forEach,但无法获得结果。

因此,filteredRecipes 应该返回这里,或者我的食谱,或者一个空数组。

提前致谢

3个回答
  • 由于 recipe.ingredients 是一个数组,因此您必须使用 .filter() 或其等效函数来检查成分是否包含搜索到的文本。

将您的 filter 函数更改为类似以下内容

function filter(recipes) {
    input.addEventListener("input", () => {
        var filteredRecipes = recipes.filter(recipe => {
            return recipe.ingredients.filter(({ingredient}) => ingredient.toLowerCase().includes(input.value.toLowerCase())).length > 0
        })
        console.log(filteredRecipes)
    })
}
ruleboy21
2022-04-18

这可能是由于 init 函数中 fetch 前面的“await”引起的。请尝试这样做;

async function init() {
        const { recipes } = getRecipes().then(res => filter(res.recipes))
        .catch(err => //catch any error
        );
}
Orçun Güler
2022-04-18

每次过滤时,您都会在输入上绑定一个事件监听器。

您只需要在启动时设置一次。

还提供更详细的替代方案:

function filter_recipes(recipes, value) {
   let ans = []
   let filter = value.toLowerCase()
   
   for (let recipe of recipes) {
     for (let item of recipe.ingredients) {
        if (item.ingredient.toLowerCase().includes(filter)) {
          ans.push(recipe)
        }
     }
   }
   
   return ans
}
madprops
2022-04-18