I see an implementation here via a recursive function, but..
I’ve tried dozens of times to compose this function, but I can’t get my head around the logic by which it should work, although at first glance it shouldn’t be so difficult. I seem to understand the points where the exit from the recursive function should occur, but it doesn’t give me anything.
I would like to understand the algorithm how it should work, in any language, perhaps at least in words, because so far I have not been able to “text” even mentally formulate what the solution should look like.
I want to implement a function to generate the resulting array in the format I need.
I have prepared the data, input and output, so that it is clearer to you what I want to achieve.
INPUT
$input = ['h1', 'p', 'h2', 'p', 'p', 'h3', 'p', 'h2', 'p', 'h3', 'p', 'h1', 'p', 'h2', 'p', 'h3', 'p'];
OUTPUT
$output = [
[
'title' => 'h1',
'descriptions' => ['p'],
'childrens' => [
[
'title' => 'h2',
'descriptions' => ['p', 'p'],
'childrens' => [
[
'title' => 'h3',
'descriptions' => ['p'],
],
]
],
[
'title' => 'h2',
'descriptions' => ['p'],
'childrens' => [
[
'title' => 'h3',
'descriptions' => ['p']
]
]
]
]
],
[
'title' => 'h1',
'descriptions' => ['p'],
'childrens' => [
[
'title' => 'h2',
'descriptions' => ['p'],
'childrens' => [
[
'title' => 'h3',
'descriptions' => ['p']
]
]
]
]
]
];
my (not working) implementation:
function parseDOM(array $inputArray): array {
$output = [];
$position = 0;
$domElementsQuantity = count($inputArray);
$parentTagLvl = 0;
function getCurrentTagLvl(string $node): bool|int
{
return match ($node) {
'h1' => 1,
'h2' => 2,
'h3' => 3,
'h4' => 4,
'h5' => 5,
'h6' => 6,
default => false,
};
}
function recursiveCreateTree(array $inputArray, int &$offsetIndex, $parentTagLvl) {
$tree = [];
$arrayItemsQuantity = count($inputArray);
while ($offsetIndex <= $arrayItemsQuantity) {
$currentNode = $inputArray[$offsetIndex];
$currentTagLvl = getCurrentTagLvl($currentNode);
if ($currentTagLvl !== false && $currentTagLvl < $parentTagLvl) {
return $tree;
}
if ($currentTagLvl === false) {
$tree['descriptions'][] = $currentNode;
} else {
$tree['title'] = $currentNode;
$tree['childrens'] = recursiveCreateTree($inputArray, $offsetIndex, $currentTagLvl);
}
$offsetIndex++;
}
return $tree;
}
while ($position <= $domElementsQuantity) {
$currentNode = $inputArray[$position];
$currentTagLvl = getCurrentTagLvl($currentNode);
if ($currentTagLvl === false) {
}
else {
if ($currentTagLvl > $parentTagLvl) {
}
else {
$parentTagLvl = $currentTagLvl - 1;
}
}
}
return $output;
}
To display the results:
echo '<pre>';
print_r(parseDOM($input));