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