1

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?

5
  • 2
    What you tried? Commented Mar 11, 2019 at 8:25
  • I tried to rebuild the following function to include a path: stackoverflow.com/questions/29384548/… I made alot of variations of the script but didnt get close to a solution, I don't think its helpful to post any of those code snippets.. Commented Mar 11, 2019 at 8:29
  • Can you please paste your code here Commented Mar 11, 2019 at 8:30
  • You can try with foreach and some logic that will work for you Commented Mar 11, 2019 at 8:33
  • I've posted my latest code snippet, don't know if it helps but I didn't get any closer to a solution (yet) Commented Mar 11, 2019 at 8:40

2 Answers 2

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
)
Sign up to request clarification or add additional context in comments.

1 Comment

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!
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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.