我正在尝试解决一个问题,我需要计算“我的三明治”等食谱的营养价值
我有一个包含“配方”和“成分”以及所需量(以千克为单位)的数据库。
食谱可以包含成分,但也可以包含其他食谱,而其他食谱又可以包含食谱/成分。
这是“测试三明治”的“零件清单”的示例,总重量为0.095千克。
array (
0 =>
array (
'id' => 2,
'name' => 'Test Cheese',
'metric_id' => 1,
'category_id' => NULL,
'quantity' => 0.015,
'depth' => 1,
),
1 =>
array (
'id' => 3,
'name' => 'Test Ham',
'metric_id' => 1,
'category_id' => NULL,
'quantity' => 0.03,
'depth' => 1,
),
2 =>
array (
'id' => 4,
'name' => 'Test Sesam Bread',
'metric_id' => 1,
'category_id' => NULL,
'quantity' => 0.05, // Only use some of the test bread (with added Sesam)
'depth' => 1,
'parts' =>
array (
0 =>
array (
'id' => 5,
'name' => 'Test Bread',
'metric_id' => 1,
'category_id' => NULL,
'quantity' => 1.0, // This a recipe for 1 kg of banana bread
'depth' => 2,
'parts' =>
array (
0 =>
array (
'id' => 6,
'name' => 'Test Flour',
'metric_id' => 1,
'category_id' => NULL,
'quantity' => 0.5,
'depth' => 3,
),
1 =>
array (
'id' => 7,
'name' => 'Test Water',
'metric_id' => 1,
'category_id' => NULL,
'quantity' => 0.3,
'depth' => 3,
),
2 =>
array (
'id' => 8,
'name' => 'Test Yeast',
'metric_id' => 1,
'category_id' => NULL,
'quantity' => 0.05,
'depth' => 3,
),
3 =>
array (
'id' => 9,
'name' => 'Test Banan',
'metric_id' => 1,
'category_id' => NULL,
'quantity' => 0.15,
'depth' => 3,
),
),
),
1 =>
array (
'id' => 10,
'name' => 'Test Sesam Seeds',
'metric_id' => 1,
'category_id' => NULL,
'quantity' => 0.1,
'depth' => 2,
),
),
),
)
如何将这种结构简化为每个“最终”成分的数量/重量列表,例如面粉,水,香蕉,奶酪,火腿,芝麻种子等?
我编写了此功能来遍历整个结构,但实际上并没有完成工作(似乎它可以正确计算总重量)
function resolveAssembly($items, $number = 1, $declaration = [])
{
$weight = 0;
foreach ($items as $item) {
// Get the quantity (weight) of the item
$amount = $item['quantity'];
// Check if the item also contains an ingredients list
if (array_key_exists('parts', $item)) {
// Get the total weight of the whole assembly
list($assembly_weight, $assembly_declaration) = resolveAssembly($item['parts'], $number * $amount, $declaration);
$declaration = array_merge($declaration, $assembly_declaration);
// Calculate the relative weight of each part in the assembly
foreach ($item['parts'] as $part) {
$weight = $weight + ($amount / $assembly_weight) * $part['quantity'];
}
} else {
// Add the amount to the declaration
if (!array_key_exists($item['name'], $declaration)) {
$declaration[$item['name']] = $number * $amount;
}
$weight = $weight + $amount;
}
}
return [$weight, $declaration];
}
编辑:合并程序集声明数组
这是我使用上述功能的方式:
$item = Inventory::findOrFail(1); // Get "Test sandwich"
$parts = $item->getAssemblyItemsList(); // Get the parts of the "Test sandwich"
$result = resolveAssembly($parts, 1); // Get total weight of 1 "Test sandwich" + a list of amount/weight of each ingredient
resolveAssembly()函数的当前结果:
0.095
[
"Test Cheese" => 0.015
"Test Ham" => 0.03
"Test Flour" => 0.025
"Test Water" => 0.015
"Test Yeast" => 0.0025
"Test Banan" => 0.0075
"Test Sesam Seeds" => 0.005 // Should have been factored in the bread ingredients
]
但这不是很正确,应该加到0.095,所以我认为Test Sesam Seeds不包括面包的成分(面粉,酵母,香蕉等)。
0.015 + 0.03 + 0.025 + 0.015 + 0.0025 + 0.0075 + 0.005 = 0.1千克的“测试三明治”
如果这有帮助,我正在使用此系统存储以下食谱:https://github.com/stevebauman/inventory/blob/v1.7/docs/ASSEMBLIES.md(但已修改为存储十进制数和负数(例如,用于处理烹饪过程中流失或添加的水))< / p>
以下是所有计算得出的“测试三明治”总重量的总和:
"Test Cheese: 0 + 0.015 = 0.015"
"Test Ham: 0.015 + 0.03 = 0.045"
"Test Flour: 0 + 0.5 = 0.5"
"Test Water: 0.5 + 0.3 = 0.8"
"Test Yeast: 0.8 + 0.05 = 0.85"
"Test Banan: 0.85 + 0.15 = 1"
"Test Flour: 0 + (1 / 1) * 0.5 = 0.5"
"Test Water: 0.5 + (1 / 1) * 0.3 = 0.8"
"Test Yeast: 0.8 + (1 / 1) * 0.05 = 0.85"
"Test Banan: 0.85 + (1 / 1) * 0.15 = 1"
"Test Sesam Seeds: 1 + 0.1 = 1.1"
"Test Bread: 0.045 + (0.05 / 1.1) * 1 = 0.09045454545"
"Test Sesam Seeds: 0.090454545454545 + (0.05 / 1.1) * 0.1 = 0.095"
答案 0 :(得分:1)
这应该使您更接近
function resolveAssembly($items) {
$weight = 0;
$declaration = [];
foreach ($items as $item) {
$weight += $item['quantity'];
if (array_key_exists('parts', $item)) {
// if there are parts, get the full weight and declaration for the sub item
list($sub_total_weight, $sub_declaration) = resolveAssembly($item['parts']);
foreach ($sub_declaration as $sub_name => $sub_weight) {
if (!array_key_exists($sub_name, $declaration)) {
$declaration[$sub_name] = 0;
}
// Total weight of particular ingredient is the sub items ingredient out of the sub items full weight
// times the quantity for this particular item
$declaration[$sub_name] += $item['quantity'] * ($sub_weight / $sub_total_weight);
}
} else {
// if there are no parts, just add the quantity
if (!array_key_exists($item['name'], $declaration)) {
$declaration[$item['name']] = 0;
}
$declaration[$item['name']] += $item['quantity'];
}
}
return [$weight, $declaration];
}
这将为您提供以下结果:
array(2) {
[0]=>
float(0.095)
[1]=>
array(7) {
["Test Cheese"]=>
float(0.015)
["Test Ham"]=>
float(0.03)
["Test Flour"]=>
float(0.022727272727273)
["Test Water"]=>
float(0.013636363636364)
["Test Yeast"]=>
float(0.0022727272727273)
["Test Banan"]=>
float(0.0068181818181818)
["Test Sesam Seeds"]=>
float(0.0045454545454545)
}
}
如果您将上述数字相加,则总数应为0.095。
基本上,当您在执行“子食谱”时,您需要知道该食谱的总“重量”是多少,然后您可以根据该子食谱的数量来计算出实际的物品总数。