将一棵树弄成扁平状并跟踪到每片叶子的路径

时间:2019-07-05 21:50:23

标签: php path tree

我有一个“食品食谱”,其中用于制作食谱的所有子成分都在树中构成

我早些时候获得了一些帮助,以创建一些代码来使树变平并计算每种基本成分(叶)的重量:How to calculate the amount of each ingredient?

但是现在我也想跟踪每种成分的制备方法(但仍要总结成分的重量)。

为此,我向每个节点添加了一个称为“准备”的额外属性

但是我很难弄清如何跟踪整个准备链。

以下是配方树结构的示例:

$tree = [
    [
        'name' => 'a',
        'weight' => 1,
        'preparation' => 'boiled',
        'tree' => [
            [
                'name' => 'c',
                'weight' => 3,
                'preparation' => 'baked',
            ],
            [
                'name' => 'c',
                'weight' => 3,
                'preparation' => 'fried',
            ],
        ]
    ],
    [
        'name' => 'b',
        'weight' => 1,
        'preparation' => 'boiled',
        'tree' => [
            [
                'name' => 'd',
                'weight' => 4,
                'preparation' => 'none',
                'tree' => [
                    [
                        'name' => 'e',
                        'weight' => 1,
                        'preparation' => 'fried',
                    ],
                    [
                        'name' => 'f',
                        'weight' => 1,
                        'preparation' => 'none',
                    ]
                ]
            ],
            [
                'name' => 'c',
                'weight' => 1,
                'preparation' => 'baked',              // b[1]c has the same "preperation chain" as a[0]c
            ]
        ]
    ],
    [
        'name' => 'c',
        'weight' => 1,
        'preparation' => 'none',
    ]
];

我希望将其减少为每个“基本成分重量”(叶)和制备链(路径)的阵列。

array (
  'c-baked,boiled'      => 0.7,
  'c-fried,boiled'      => 0.5,
  'e-fried,none,boiled' => 0.4,
  'f-none,none,boiled'  => 0.4,
  'c-none'              => 1,
)

出于争论的目的,在不考虑准备的情况下,结果如下所示:

array (
  'c' => 2.2,   // 0.7 + 0.5 + 1
  'e' => 0.4,
  'f' => 0.4,
)

我只能获得跟踪基本成分(叶)而不是完整链的制备的代码:

array (
  'c-baked,boiled' => 0.2,
  'c-fried,boiled' => 0.5,
  'e-fried,none,boiled' => 0.4,
  'f-none,none,boiled' => 0.4,
  'c-none' => 1,
)

这是代码的外观:

//function getBaseIngredients(array $tree): array
function getBaseIngredients(array $tree, $preparation = null): array
{
    $leafs = [];

    // Loop through the nodes in the tree if the node 
    // is a leaf we sum the weight, otherwise we recursivly
    // call our self and resolve the branch
    foreach($tree as $node){
        if(empty($node['tree']))
        {

            // if there are no parts, just add the weight

            //$key = $node['name'] . '-' . $node['preparation'];
            $key = $node['name'] . '-' . $node['preparation'] . $preparation;

            if(!array_key_exists($node['name'], $leafs)) {
                $leafs[$key] = 0;
            }

            $leafs[$key] += $node['weight'];

        } else {

            // if there sub nodes, get the full weight node
            $nodes = getBaseIngredients($node['tree'], $preparation);
            $total = array_sum($nodes);

            // Scale each sub node according to the parent
            foreach($nodes as $key => $weight){

                if(!array_key_exists($key, $leafs)) {
                    //$leafs[$key] = 0;
                    $leafs[$key . ',' . $node['preparation']] = 0;
                }

                // Total weight of particular node is the 
                // sub node out of the sub node full weight
                // times the weight for this particular leaf

                // $leafs[$key] += $node['weight'] * ($weight / $total);
                $leafs[$key . ',' . $node['preparation']] += $node['weight'] * ($weight / $total);
            }
        }
    }

    return $leafs;
}

0 个答案:

没有答案