tom-g
tom-g

Reputation: 125

PHP Branching Recursion With Repeating Children

I have a flat structure that I need to convert to a nested tree-like structure. This is different from other Stack Overflow questions because the children can repeat (i.e. can have the same questionId and parentId). I have attempted to solve this with branching recursion with no luck.

Input (flat array):

[
    [
        'questionId' => 1,
        'name' => 'albumName',
        'parentId' => 0,
        'answer' => "Name of album",
    ],
    [
        'questionId' => 2,
        'name' => 'albumGenre',
        'parentId' => 0,
        'answer' => "album genre",
    ],
    [
        'questionId' => 3,
        'name' => 'trackStart',
        'parentId' => 0,
    ],
    [
        'questionId' => 4,
        'name' => 'trackName',
        'parentId' => 3,
        'answer' => "Track One",
    ],
    [
        'questionId' => 5,
        'name' => 'trackEnd',
        'parentId' => 3,
    ],
    [
        'questionId' => 3,
        'name' => 'trackStart',
        'parentId' => 0,
    ],
    [
        'questionId' => 4,
        'name' => 'trackName',
        'parentId' => 3,
        'answer' => "Track Two",
    ],
    [
        'questionId' => 6,
        'name' => 'artistStart',
        'parentId' => 3,
    ],
    [
        'questionId' => 7,
        'name' => 'artistName',
        'parentId' => 6,
        'answer' => "Artist Name",
    ],
    [
        'questionId' => 8,
        'name' => 'artistEnd',
        'parentId' => 6,
    ],
    [
        'questionId' => 5,
        'name' => 'trackEnd',
        'parentId' => 3,
    ],
    [
        'questionId' => 9,
        'name' => 'albumDate',
        'parentId' => 0,
        'answer' => "album Date",
    ]       
]

Desired Output (nested array):

[
    'albumName' => 'Album Name',
    'albumGenre' => 'Album Genre',
    'trackStart' => [
        [
            'trackName' => 'Track One'
        ],
        [
            'trackName' => 'Track Two',
            'artistStart' => [
                [
                    'artistName' => 'Artist Name'
                ]
            ]
        ]
    ],
    'albumDate' => 'album Date'
]

Upvotes: 1

Views: 53

Answers (1)

MeMReS
MeMReS

Reputation: 91

You can solve this using Reference Pointers:

$newArray = array();
$pointer[] = &$newArray;

foreach($arr as $ar) {

    if(stristr($ar['name'], "start")) {  // Start

        $pointer[] = &$pointer[count($pointer)-1][$ar['name']][];

    } else if(stristr($ar['name'], "end")) {  // End

        array_pop($pointer);

    } else {

        $pointer[count($pointer)-1][$ar['name']] = $ar['answer'];

    }
}

To make it faster you can use stripos($ar['name'], "start") !== false;

Upvotes: 1

Related Questions