Php 在层次数组中转换简单数组

Php 在层次数组中转换简单数组,php,arrays,multidimensional-array,hierarchy,hierarchical-clustering,Php,Arrays,Multidimensional Array,Hierarchy,Hierarchical Clustering,我在下面有多个条目的数组中循环。在这个例子中,我有3个元素,其中每个元素都有3个值 [0] ['name'] => 'aaa' ['id'] => 38679 ['parent-id'] => 0 [1] ['name'] => 'bbb' ['id'] => 38830 ['parent-id'] => 38679 [2] ['name'] => 'ccc' ['id'] => 38680 [

我在下面有多个条目的数组中循环。在这个例子中,我有3个元素,其中每个元素都有3个值

[0]
   ['name'] => 'aaa'
   ['id'] => 38679
   ['parent-id'] => 0
[1]
   ['name'] => 'bbb'
   ['id'] => 38830
   ['parent-id'] => 38679
[2]
   ['name'] => 'ccc'
   ['id'] => 38680
   ['parent-id'] => 38830
因此,通过数组循环,我需要以这种格式构造另一个数组(其思想是构造层次结构):


也许还有别的办法。任何建议都很好。

可能的解决方案之一是使用递归函数:

$test = [
    0 => [
        'name' => 'aaa',
        'id' => 38679,
        'parent-id' => 0
    ],
    1 => [
        'name' => 'bbb',
        'id' => 38830,
        'parent-id' => 38679
    ],
    2 => [
        'name' => 'ccc',
        'id' => 38680,
        'parent-id' => 38830
    ]
];

function make_hierarchy(array $arr, $parent = 0) {
    $result = array();

    foreach($arr as $item) {
        if ($item['parent-id'] == $parent) {
            $children = make_hierarchy($arr, $item['id']);
            $child = $item;
            if ($children) {
                $child['children'] = $children;
            }
            $result[] = $child;
        }
    }
    return $result;
}

$r = make_hierarchy($test);

var_dump($r);
迭代解决方案:

// set up test data
$arr = [
    0 => [
        'name' => 'aaa',
        'id' => 38679,
        'parent-id' => 0
        ],
    1 => [
        'name' => 'bbb',
        'id' => 38830,
        'parent-id' => 38679
        ],
    2 => [
        'name' => 'ccc',
        'id' => 38680,
        'parent-id' => 38830
        ]
    ];

// hierarchy array that will have the result
$hier = [];

// Start off by putting all nodes as top-level nodes in the hierarchy
foreach ($arr as $node) {
    $node['children'] = [];
    $hier[$node['id']] = $node;
};

// Iterate to move nodes from the top-level under their respective parents.
do {
    $count = count($hier);
    echo 'Next iteration: ', $count, ' top-level nodes left<br>';

    // Collect the ids of parents of top-level nodes 
    $parents = [];
    foreach ($hier as $node) {
        $parents[$node['parent-id']] = 1;
    }

    // Find all nodes that are candidate to be moved     
    foreach ($hier as $node) {
        // Treat node only if it has gathered all of its children
        if (!array_key_exists($node['id'], $parents)) {
            $parentId = $node['parent-id'];
            // Remove the parent-id attribute, it is not needed anymore
            unset($node['parent-id']);
            // Remove the node from the top-level
            unset($hier[$node['id']]);
            // Check that referenced parent exists, parent-id=0 will fail this.
            if (array_key_exists($parentId, $hier)) {
                // Move this node under its parent node, keyed by its ID
                echo 'Node ', $node['id'], ' moved under ', $parentId, '<br>';
                $hier[$parentId]['children'][$node['id']] = $node;
            } else {
                // Node is stays on top-level (but without parent-id property):
                echo 'Node ', $node['id'], ' stays at top level<br>';
                $hier[] = $node;
            }
        }
    };
    // keep going as long as we were able to move at least one node 
} while (count($hier) < $count);

echo 'Done. <pre>';    
print_r($hier);
echo '</pre>';    

这不是等级制度,也不清楚你想要什么。你想要的阵列背后的逻辑是什么?基于
id
parent id
元素的层次结构类似于
aaa->bbb->ccc
,其中
bbb
aaa
的子元素,依此类推。这就是你想要的吗?你说得对Timofey,我用错阵列了。我编辑了这个问题。
$result[]=$child
给出错误--
$child
未声明。代码现在运行,但输出没有任何id属性,数组的索引也没有对应于id值。不知何故,“ccc”的节点丢失了。结果只有两个节点具有name属性('aaa'和'bbb')。好的,编辑答案。在你有算法的情况下,添加特定的内容并不是什么大问题。在输出中有“ccc”节点的修复方法吗?您还应更改为:
$result[$item['id']]=$child谢谢,我不知怎么错过了这个问题。
// set up test data
$arr = [
    0 => [
        'name' => 'aaa',
        'id' => 38679,
        'parent-id' => 0
        ],
    1 => [
        'name' => 'bbb',
        'id' => 38830,
        'parent-id' => 38679
        ],
    2 => [
        'name' => 'ccc',
        'id' => 38680,
        'parent-id' => 38830
        ]
    ];

// hierarchy array that will have the result
$hier = [];

// Start off by putting all nodes as top-level nodes in the hierarchy
foreach ($arr as $node) {
    $node['children'] = [];
    $hier[$node['id']] = $node;
};

// Iterate to move nodes from the top-level under their respective parents.
do {
    $count = count($hier);
    echo 'Next iteration: ', $count, ' top-level nodes left<br>';

    // Collect the ids of parents of top-level nodes 
    $parents = [];
    foreach ($hier as $node) {
        $parents[$node['parent-id']] = 1;
    }

    // Find all nodes that are candidate to be moved     
    foreach ($hier as $node) {
        // Treat node only if it has gathered all of its children
        if (!array_key_exists($node['id'], $parents)) {
            $parentId = $node['parent-id'];
            // Remove the parent-id attribute, it is not needed anymore
            unset($node['parent-id']);
            // Remove the node from the top-level
            unset($hier[$node['id']]);
            // Check that referenced parent exists, parent-id=0 will fail this.
            if (array_key_exists($parentId, $hier)) {
                // Move this node under its parent node, keyed by its ID
                echo 'Node ', $node['id'], ' moved under ', $parentId, '<br>';
                $hier[$parentId]['children'][$node['id']] = $node;
            } else {
                // Node is stays on top-level (but without parent-id property):
                echo 'Node ', $node['id'], ' stays at top level<br>';
                $hier[] = $node;
            }
        }
    };
    // keep going as long as we were able to move at least one node 
} while (count($hier) < $count);

echo 'Done. <pre>';    
print_r($hier);
echo '</pre>';    
Next iteration: 3 top-level nodes left
Node 38680 moved under 38830
Next iteration: 2 top-level nodes left
Node 38830 moved under 38679
Next iteration: 1 top-level nodes left
Node 38679 stays at top level
Done.

Array
(
    [38831] => Array
        (
            [name] => aaa
            [id] => 38679
            [children] => Array
                (
                    [38830] => Array
                        (
                            [name] => bbb
                            [id] => 38830
                            [children] => Array
                                (
                                    [38680] => Array
                                        (
                                            [name] => ccc
                                            [id] => 38680
                                            [children] => Array
                                                (
                                                )
                                        )
                                )
                        )
                )
        )
)