我有一个以下结构类别的树:
[6] => Array
(
[id] => 6
[name] => computers
[productCount] => 0
[children] => Array
(
[91] => Array
(
[id] => 91
[name] => notebook
[productCount] => 5
[children] => Array
(
)
)
[86] => Array
(
[id] => 86
[name] => desktop
[productCount] => 0
[children] => Array
(
)
)
)
)
除了子类别,每个类别可能包含产品(如文件夹可能包含子文件夹和文件)。
我正在尝试编写一个递归函数,我希望将此数组作为参考,并使用[productCount] = 0和包含此类空节点的所有父类别去除两个叶类别。换句话说,在处理之后,我想只有那些在任何子级别上持有产品的类别。
我已经写了一些代码,现在调试它并且它不会剥离空节点。可能是我没有正确使用引用。如果可能的话,请帮我解决。
function pruneTree( & $node) {
if ( ! $node['children'] && ! $node['productCount']) {
unset($node);
}
if ( ! empty($node['children'])) {
foreach ($node['children'] as $key => $child) {
pruneTree($node['children'][$key]);
}
}
return;
}
答案 0 :(得分:5)
unset
仅删除引用但不删除引用的变量:
如果函数内部的PASSED BY REFERENCE变量为
unset()
,则仅销毁本地变量。调用环境中的变量将保留与调用unset()
之前相同的值。
所以你需要传递父数组和键来删除那个变量:
function pruneTree(&$parent, $key) {
$node = &$parent[$key];
if (!$node['children'] && !$node['productCount']) {
unset($parent[$key]);
}
if (!empty($node['children'])) {
foreach ($node['children'] as $key => &$child) {
pruneTree($node['children'], $key);
}
}
}
答案 1 :(得分:4)
您还可以更改函数中的参数以获取节点数组而不是单个节点。这会稍微改变递归,并且无需传递密钥:
function pruneTree(&$nodes) {
foreach ($nodes as $key => $node) {
if (!$node['children'] && !$node['productCount']) {
unset($nodes[$key]);
} elseif (!empty($node['children'])) {
pruneTree($nodes[$key]['children']);
// This line checks if all the children have been pruned away:
if (empty($nodes[$key]['children'])) {
unset($nodes[$key]);
}
}
}
}
此外,添加了一个检查,确保如果修剪了所有子节点,则父(现在,叶)节点也会被修剪。
希望这有帮助!
测试数据:
$data = array(
6 => array(
'id' => 6,
'name' => 'computers',
'productCount' => 0,
'children' => array(
91 => array(
'id' => 91,
'name' => 'notebook',
'productCount' => 5,
'children' => array()
),
86 => array(
'id' => 86,
'name' => 'desktop',
'productCount' => 0,
'children' => array()
)
)
)
);
致电:
pruneTree($data);
echo '<pre>';
print_r($data);
echo '</pre>';
答案 2 :(得分:2)
我会这样做。请注意&#34;&amp;&#34;在foreach。
function pruneTree(&$node)
{
foreach ($node as $index => &$value) {
if (empty($value)) {
unset($node[$index]);
} elseif (is_array($value)) {
pruneTree($value);
}
}
}
答案 3 :(得分:0)
我不知道是不是这种情况,但是当我需要在数组中递归地更改值时,我需要传递&amp;也是对foreach的价值。
private function convertXMLPart(&$array) {
foreach ($array as $rowKey => &$row) {
if (gettype($row) != 'string') {
$row = (array)$row;
if (!empty($row['@attributes'])) {
foreach ($row['@attributes'] as $key => $value) {
$row[$key] = $value;
}
unset($row['@attributes']);
$array[$rowKey] = $row;
}
$this->convertXMLPart($row);
}
}
}