I have a problem building an unordered list from multidimensional array containing entities and their children. The problem is I do not want to use recursion as the tree could get very deep and recursion could produce unnecessary load on server.
This is an example of such an array (it is simplified just to contain title and children and the entities could also be objects).
$array = array(
array('title' => '1', 'children' => array()),
array('title' => '2', 'children' => array()),
array('title' => '3', 'children' => array()),
array('title' => '4', 'children' => array(
array('title' => '41', 'children' => array()),
array('title' => '42', 'children' => array()),
array('title' => '43', 'children' => array()),
array('title' => '44', 'children' => array(
array('title' => '441', 'children' => array()),
array('title' => '442', 'children' => array()),
array('title' => '443', 'children' => array()),
array('title' => '444', 'children' => array(
array('title' => '4441', 'children' => array()),
array('title' => '4442', 'children' => array()),
array('title' => '4443', 'children' => array())
)),
)),
array('title' => '45', 'children' => array())
)),
array('title' => '5', 'children' => array()),
array('title' => '6', 'children' => array(
array('title' => '61', 'children' => array()),
array('title' => '62', 'children' => array()),
array('title' => '63', 'children' => array())
)),
array('title' => '7', 'children' => array())
);
Doing some research here on SO I came up with this solution that is very close to my desired one:
<html>
<head></head>
<body>
<ul>
<?php
$stack = $array;
$i = 0;
$counts = array();
while(!empty($stack)) {
$node = array_shift($stack);
echo "<li>{$node['title']}";
if($node['children']) {
echo "<ul>";
$counts[] = count($node['children']);
$node['children'] = array_reverse($node['children']);
foreach($node['children'] as $ch)
array_unshift($stack, $ch);
}
if(!empty($counts)) {
end($counts);
if($counts[$key] == 0) {
echo "</ul>";
array_pop($counts);
} else {
$counts[$key]--;
}
}
if(!$node['children']) {
echo "</li>";
}
// just to make sure we won't end in infinite loop
$i++;
if($i == 50) break;
}
?>
</ul>
</body>
</html>
The output is below – as You can see, the problem I have is only the closing </ul> for the sub-trees. My questions: am I overthinking it or am I blind and don’t see an obvious mistake? Could You please push me forward to finite solution or give me Your own?
The output:
- 1
- 2
- 3
- 4
- 41
- 42
- 43
- 44
- 441
- 442
- 443
- 444
- 4441
- 4442
- 4443
- 45
- 5
- 6
- 61
- 62
- 63
- 7
OK, as it usually goes –
ask for a solution You are solving for hours and immediately You are out with one...– so did I some more thinking after a small relax and came up with this solution:The problem was I was missing another
whilethat should subtract the$countsvalue all the way back up the tree…I will wait with accepting my own answer just in the case somebody would post their better solution that should be accepted rather than my not so neat solution.