【问题标题】:Converting a flat array to a specific array format将平面数组转换为特定数组格式
【发布时间】:2015-12-23 22:44:34
【问题描述】:

各位 PHP 程序员,请考虑以下 DB 结果:

+---------+-----------+---------------+--------+
| node_id | parent_id | path          | branch |
+---------+-----------+---------------+--------+
|       1 |         0 | /1/           |   NULL |
|       2 |         1 | /1/2/         |   NULL |
|       3 |         2 | /1/2/3/       |      1 |
|       4 |         3 | /1/2/3/4/     |      1 |
|       8 |         4 | /1/2/3/4/8/   |      1 |
|       9 |         8 | /1/2/3/4/8/9/ |      1 |
|       7 |         4 | /1/2/3/4/7/   |      0 |
|       5 |         2 | /1/2/5/       |      0 |
|       6 |         5 | /1/2/5/6/     |      0 |
+---------+-----------+---------------+--------+

如何获得以下 PHP 数组:

[
    [
        'id' => 1,
        'parentId' => 0,
    ],
    [
        'id' => 2,
        'parentId' => 1,
        'nodes' => [
            [ // when branch == 0
                [
                    'id' => 5,
                    'parentId' => 2
                ],
                [
                    'id' => 6,
                    'parentId' => 5
                ],
            ],
            [ // when branch == 1
                [
                    'id' => 3,
                    'parentId' => 2
                ],
                [
                    'id' => 4,
                    'parentId' => 3,
                    'nodes' => [
                        [ // when branch == 0
                            [
                                'id' => 7,
                                'parentId' => 4
                            ],
                        ],
                        [ // when branch == 1
                            [
                                'id' => 8,
                                'parentId' => 4
                            ],
                            [
                                'id' => 9,
                                'parentId' => 8
                            ],
                        ]
                    ]
                ],
            ]
        ]
    ]
]

该功能应该具有无限的深度。

任何帮助将不胜感激,因为我一直在碰壁。

【问题讨论】:

  • 请给我们看看墙(我指的是墙,我的意思是你尝试过的xD)...
  • 我的尝试包括通过 id 进行一次通过索引,然后通过第二次通过找出放置具有分支的节点的位置。它仅适用于一级递归,并且与您在此处看到的非常相似:blog.tekerson.com/2009/03/03/…。不幸的是,我因为沮丧而删除了它;)

标签: php arrays nested adjacency-matrix


【解决方案1】:

类似这样的:

function buildTree($arr, $parentID)
{
    $children = [];
    foreach ($arr as $item) {
        if ($item['parent_id'] == $parentID) {
            array_push($children, [
                'id'       => $item['node_id'],
                'parentId' => $item['parent_id'],
                'nodes'    => buildTree($arr, $item['node_id'])
            ]);
        }
    }

    return $children;
}

$tree = buildTree($flat, null);

更新:

function getBranches($arr, $parentID)
{
    $branches = array();

    foreach ($arr as $item) {
        if ($item['parent_id'] == $parentID) {

            $bKey = $item['branch'];
            $node = array(
                'id'       => $item['node_id'],
                'parentId' => $item['parent_id']
            );

            $firstNodeChild = false;
            if ($nodeChildren = getBranches($arr, $item['node_id'])) {
                $hasKey = array_key_exists($bKey, $nodeChildren);
                if ($hasKey && $nodeChildren[$bKey]) {
                    if (sizeof($nodeChildren[$bKey]) == 1) {
                        $firstNodeChild = $nodeChildren[$bKey][0];
                        unset($nodeChildren[$bKey]);
                    }
                }
                if ($nodeChildren) {
                    $node['nodes'] = $nodeChildren;
                }
            }
            if (!array_key_exists($bKey, $branches)) {
                $branches[$bKey] = array();
            }
            $branches[$bKey][] = $node;
            if (false !== $firstNodeChild) {
                $branches[$bKey][] = $firstNodeChild;
            }

        }
    }
    ksort($branches);

    return $branches;
}

$tree = getBranches($arr, 0);

【讨论】:

  • 这实际上很接近,但返回的数组没有预期的布局。在您的尝试中,每个节点都插入到前一个节点的“节点”属性中。这就是我们希望孩子有分支的行为。如果一个节点是另一个没有分支属性的节点的直接后代,则它应该是兄弟节点而不是子节点(如果有意义的话)。
  • 当孩子不存在时,您不想创建“节点”键吗?
  • 没有。您的结果以 [0 => [id=>1, nodes=>[[id=>2, nodes=>[...]]]] 开头,而预期结果应以 [0 => [id=>1], 1=>[id=>2, nodes=>[...]]] 开头
  • 你 id=>2 有父 id=>1(数据库结果),我的树结果是正确的。您可以通过生成
    • 嵌套列表
    来检查(查看)它
  • 我已经尝试了您的代码,结果数组与问题的预期输出不匹配。您的结果:gist.github.com/mfauveau/821d04f3348add917919,预期结果:gist.github.com/mfauveau/b2296fdd5fb04f1bfdb7
猜你喜欢
  • 2020-10-01
  • 1970-01-01
  • 2020-03-22
  • 2020-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多