0

I've built a recursive PHP function to create a multidimensional array with parents/children. Now I want to create a function to create a list with paths to each array item. See the following array:

$testdata = [
    ['id' => 1, 'parent_id' => null, 'desc' => 'Vehicles'],
    ['id' => 2, 'parent_id' => 1, 'desc' => 'Cars'],
    ['id' => 3, 'parent_id' => 1, 'desc' => 'Motorbikes'],
    ['id' => 4, 'parent_id' => 1, 'desc' => 'Planes'],
    ['id' => 5, 'parent_id' => 2, 'desc' => 'Toyota'],
    ['id' => 6, 'parent_id' => 2, 'desc' => 'Volkswagen'],
    ['id' => 7, 'parent_id' => 2, 'desc' => 'Renault'],
    ['id' => 8, 'parent_id' => 3, 'desc' => 'Honda'],
    ['id' => 9, 'parent_id' => 3, 'desc' => 'Yamaha'],
    ['id' => 10, 'parent_id' => 4, 'desc' => 'Boeing'],
    ['id' => 11, 'parent_id' => null, 'desc' => 'Cities'],
    ['id' => 12, 'parent_id' => 11, 'desc' => 'Amsterdam'],
    ['id' => 13, 'parent_id' => 11, 'desc' => 'New York'],
];

Now the expected result should be like this:

$output = [
    'Vehicles'
    'Vehicles\Cars'
    'Vehicles\Cars\Toyota'
    'Vehicles\Cars\Volkswagen'
    'Vehicles\Cars\Renault'
    'Vehicles\Motorbikes'
    'Vehicles\Motorbikes\Honda'
    'Vehicles\Motorbikes\Yamaha'
    'Vehicles\Planes'
    'Vehicles\Planes\Boeing'
    'Cities'
    'Cities\Amsterdam'
    'Cities\New York'
];

I have tried to rebuild my recursive function, but I can't wrap my head around it. Could you guys give me some advice or a push me in the right direction?

Nigel Ren
  • 56,122
  • 11
  • 43
  • 55
Vinze
  • 45
  • 4

2 Answers2

1

This way solves the problem by building both the output as well as a hierarchy of items as you go along. So each time you get a new item, you build a string which represents the 'parent text' as well as adding to the output the current item. When the parent is referred to later - it can just pick out the built up text form $levels rather than having to rebuild it...

$output = [];
$levels = [];
foreach ( $testdata as $entry ) {
    if ( $entry["parent_id"] == null )  {
        $text = $entry["desc"];
    }
    else    {
        $text = $levels[$entry["parent_id"]] . "/" . $entry["desc"]; 
    }
    $levels[$entry["id"]] = $text;
    $output [] = $text;
}
// Optionally sort output to group items
sort($output);
print_r($output);

The sort will group the items together - otherwise they will appear in the order they are in the input array.

Output with sort...

Array
(
    [0] => Cities
    [1] => Cities/Amsterdam
    [2] => Cities/New York
    [3] => Vehicles
    [4] => Vehicles/Cars
    [5] => Vehicles/Cars/Renault
    [6] => Vehicles/Cars/Toyota
    [7] => Vehicles/Cars/Volkswagen
    [8] => Vehicles/Motorbikes
    [9] => Vehicles/Motorbikes/Honda
    [10] => Vehicles/Motorbikes/Yamaha
    [11] => Vehicles/Planes
    [12] => Vehicles/Planes/Boeing
)
Nigel Ren
  • 56,122
  • 11
  • 43
  • 55
  • Oh wow, that was actually much simpler than I expected. I thought I needed to use a recursive function and didn't even think of this. Thank you very much! – Vinze Mar 11 '19 at 10:00
0

I have tried the following function:

<?php
function buildList($items, $parent_id = null, $path = '') {
    $paths = [];
    foreach ($items as $item) {
        if ($item['parent_id'] == $parent_id) {
            $paths[] = buildList($items, $item['id'], $path.'/'.$item['desc']);
        }
    }
    return $paths;
}

I haven't got any closer to a solution unfortunately, but I think this should go to the right direction.

Vinze
  • 45
  • 4