Php 在层次数组中转换简单数组
我在下面有多个条目的数组中循环。在这个例子中,我有3个元素,其中每个元素都有3个值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 [
[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
(
)
)
)
)
)
)
)