我有一个像这样的数组:
const state = {
products: [
{ name: "Potato", amount: "3"},
{ name: "Butter", amount: "1000" },
{ name: "Salt", amount: "2000" },
//{name: "Egg", amount: "10"},
{ name: "Tomato", amount: "5"},
{ name: "Sour Milk", amount: "5"}
],
recipes: [
{
name: "Mashed potatoes",
ingredients: [
{ name: "Potato", amount: "5"},
{ name: "Butter", amount: "30"},
{ name: "Salt", amount: "15"}
],
instructions: "Some Text"
},
{
name: "Tomato Omelette",
ingredients: [
{ name: "Tomato", amount: "1" },
{ name: "Egg", amount: "1" },
{ name: "Salt", amount: "10" },
{ name: "Butter", amount: "40" }
],
instructions: "Some text"
}
]
};
我想通过我可以用我的产品烹饪的食谱过滤我的食谱数组(在这种情况下,我不能煮“西红柿煎蛋”,因为我没有鸡蛋,也不能煮“土豆泥”,因为我没有足够的土豆)。
到目前为止,我尝试了不同的方法,但并未提出完整的解决方案。
我最接近的解决方案是这样:
const filterRecipes = (filter, products, recipes) => {
if(filter === 'available products') {
//Getting all product names for future tests
const productsNames = products.map(item => item.name);
//Here we will filter all our recipes by available products
const result = recipes.filter(recipe => {
//Getting all ingredient names of the current recipe
const ingredientNames = recipe.ingredients.map(item => item.name);
//If we have all products for our recipe
//we will add it to our filtered array
if (ingredientNames.every((name) => productsNames.includes(name))){
return true;
}
})
console.log(result);
}
};
此名称仅适用于产品名称,不适用于其数量。当我尝试检查金额时,它就坏了。
这是整个代码:
const state = {
products: [
{ name: "Potato", amount: "5"},
{ name: "Butter", amount: "1000" },
{ name: "Salt", amount: "2000" },
//{name: "Egg", amount: "10"},
{ name: "Tomato", amount: "5"},
{ name: "Sour Milk", amount: "5"}
],
recipes: [
{
name: "Mashed potatoes",
ingredients: [
{ name: "Potato", amount: "5"},
{ name: "Butter", amount: "30"},
{ name: "Salt", amount: "15"}
],
instructions: "Some Text"
},
{
name: "Tomato Omelette",
ingredients: [
{ name: "Tomato", amount: "1" },
{ name: "Egg", amount: "1" },
{ name: "Salt", amount: "10" },
{ name: "Butter", amount: "40" }
],
instructions: "Some text"
}
]
};
const filterRecipes = (filter, products, recipes) => {
if(filter === 'available products') {
//Getting all product names for future tests
const productsNames = products.map(item => item.name);
//Here we will filter all our recipes by available products
const result = recipes.filter(recipe => {
//Getting all ingredient names of the current recipe
const ingredientNames = recipe.ingredients.map(item => item.name);
//If we have all products for our recipe
//we will add it to our filtered array
if (ingredientNames.every((name) => productsNames.includes(name))){
return true;
}
})
console.log(result);
}
};
filterRecipes("available products", state.products, state.recipes);
答案 0 :(得分:2)
我们可以这样做:
productsObj
以允许快速查找productsObj
中,并且含量是否大于或等于配方配料中的项目。
const state = {
products: [
{ name: "Potato", amount: "5" },
{ name: "Butter", amount: "1000" },
{ name: "Salt", amount: "2000" },
{ name: "Egg", amount: "10" },
{ name: "Tomato", amount: "5" },
{ name: "Sour Milk", amount: "5" }
],
recipes: [
{
name: "Mashed potatoes",
ingredients: [
{ name: "Potato", amount: "5" },
{ name: "Butter", amount: "30" },
{ name: "Salt", amount: "15" }
],
instructions: "Some Text"
},
{
name: "Tomato Omelette",
ingredients: [
{ name: "Tomato", amount: "1" },
{ name: "Egg", amount: "1" },
{ name: "Salt", amount: "10" },
{ name: "Butter", amount: "40" }
],
instructions: "Some text"
}
]
};
const filterRecipes = (filter, products, recipes) => {
if (filter === "available products") {
//Getting all product names in an object for fast look-up
const productsObj = products.reduce((aggObj, item) => {
aggObj[item.name] = item;
return aggObj;
}, {});
//console.log("o", productsObj);
//Here we will filter all our recipes by available products
const result = recipes.filter((recipe) => {
let valid = true; //true until proven false
//Loop over ingredients of each recipe
for (let i = 0; i < recipe.ingredients.length; i++) {
const item = recipe.ingredients[i];
const lookup = productsObj[item.name] || false;
const quantityEnough = lookup
? parseInt(lookup.amount) >= parseInt(item.amount)
: false;
if (!quantityEnough) {
valid = false;
break;
}
}
return valid;
});
console.log(result);
}
};
filterRecipes("available products", state.products, state.recipes);
.as-console-wrapper { max-height: 100% !important; top: 0; }
例如,如果您将产品数量更改为:
const state = {
products: [
{ name: "Potato", amount: "4" },
{ name: "Butter", amount: "1000" },
{ name: "Salt", amount: "2" },
{ name: "Egg", amount: "10" },
{ name: "Tomato", amount: "5" },
{ name: "Sour Milk", amount: "5" }
],
由于盐和土豆的数量不足,无法获得任何结果。
答案 1 :(得分:1)
您可以使用一个对象来加快访问速度,将amount
用作数字以提高可比性
{
Potato: 5,
Butter: 1000,
Salt: 2000,
Tomato: 5,
"Sour Milk": 5
}
只循环一次产品和回执。
此方法使用destructuring assignment,其中属性是从对象中取出的。
它使用对象的值并检查所有成分的可用量。
const
filter = ({ products, recipes }) => {
const avalilable = products.reduce((r, { name, amount }) => (r[name] = +amount, r), {});
console.log(avalilable )
return recipes.filter(({ ingredients }) =>
ingredients.every(({ name, amount }) => avalilable[name] >= +amount));
},
state = { products: [{ name: "Potato", amount: "5" }, { name: "Butter", amount: "1000" }, { name: "Salt", amount: "2000" }, { name: "Tomato", amount: "5" }, { name: "Sour Milk", amount: "5" }], recipes: [{ name: "Mashed potatoes", ingredients: [{ name: "Potato", amount: "5" }, { name: "Butter", amount: "30" }, { name: "Salt", amount: "15" }], instructions: "Some Text" }, { name: "Tomato Omelette", ingredients: [{ name: "Tomato", amount: "1" }, { name: "Egg", amount: "1" }, { name: "Salt", amount: "10" }, { name: "Butter", amount: "40" }], instructions: "Some text" }] },
recipes = filter(state);
console.log(recipes);
答案 2 :(得分:0)
您可以尝试此解决方案。
在这里,我添加了一个解决方案,例如,您有
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>Drag</title> </head> <body> <div id="draggable"></div> </body> </html>
个单位的“盐” ,并且第一个配方需要20
个单位进行烹饪现在假设,第二个配方需要
15
单位盐,但是您的商店还有10
单位盐。在这种情况下,您不能 第二道菜。
5
const state = {
products: [
{ name: "Potato", amount: "5"},
{ name: "Butter", amount: "1000" },
{ name: "Salt", amount: "20" },
{ name: "Egg", amount: "1"},
{ name: "Tomato", amount: "5"},
{ name: "Sour Milk", amount: "5"}
],
recipes: [
{
name: "Mashed potatoes",
ingredients: [
{ name: "Potato", amount: "5"},
{ name: "Butter", amount: "30"},
{ name: "Salt", amount: "15"}
],
instructions: "Some Text"
},
{
name: "Tomato Omelette",
ingredients: [
{ name: "Tomato", amount: "1" },
{ name: "Egg", amount: "1" },
{ name: "Salt", amount: "10" },
{ name: "Butter", amount: "40" }
],
instructions: "Some text"
}
]
};
const filterRecipes = (filter, products, recipes) => {
if (filter === 'available products') {
/**
* Restructure the products from array to object.
* like {Potato: "20", "Salt": "200"}
*/
const store = products.reduce((a, {name, amount}) => {
return {...a, [name]: amount};
}, {});
const canCook = recipes.filter(recipe => {
/**
* Convert ingredient from array to object like products
*
*/
const ingredients = recipe.ingredients.reduce((a, {name, amount}) => {
return {...a, [name]: amount};
}, {});
/**
* Check if every ingredients are available at the store
*/
const allow = Object.entries(ingredients).every(([name, amount]) => {
return (store[name] !== undefined && (+store[name]) >= (+amount));
});
/**
* This is for reducing the amount of ingredient from the store
* if the recipe is taken for cooking.
* You can omit it if you don't need to measure this factor.
*/
if (allow) {
Object.entries(ingredients).forEach(([name, amount]) => {
store[name] -= amount;
});
}
return allow;
});
console.log(canCook);
}
}
filterRecipes("available products", state.products, state.recipes);