1

I'm stuck with transforming flat array to multidimensional tree like. I have already done it, but I used references, which creates another set of problems down the line, so I need to do this without references.

Input array:

Array
[
1 =>[
        'content_id' => 1,
        'sort_order' => 1,
        'level' => 1
    ],
2 =>[
        'content_id' => 7,
        'sort_order' => 2,
        'level' => 2
    ],
3 =>[
        'content_id' => 4,
        'sort_order' => 3,
        'level' => 2
    ],
4 =>[
        'content_id' => 2,
        'sort_order' => 4,
        'level' => 3
    ],
5 =>[
        'content_id' => 3,
        'sort_order' => 5,
        'level' => 1
    ],
6 =>[
        'content_id' => 6,
        'sort_order' => 6,
        'level' => 1
    ],
7 =>[
        'content_id' => 5,
        'sort_order' => 7,
        'level' => 2
    ]
]

Output array:

1 => [
    'id' = 1,
    'visited' = 0,
    'children' => [
             2 => [
                  'id' => 7,
                  'visited' => 0,
                  'children' => []
             ],
             3 => [
                  'id' => 4,
                  'visited' => 0,
                  'children' => [
                           4 => [
                                'id' = 2,
                                'visited' = 0,
                                'children' => []
                           ]
             ]
],
5 => [
     'id' => 3,
     'visited' => 0,
     'children' => []
],
6 => [
     'id' => 6,
     'visited' => 0,
     'children' => [
             7 => [
                  'id' => 5,
                  'visited' => 0,
                  'children => []
             ]
]
]

Any idea how to tackle a problem like this without having direct parent relation set? I can use recursion, but references are problem.

5
  • 1
    you have 2 the same questions. Delete one of them Commented Jul 28, 2015 at 11:39
  • I dont see corelation between building tree-like array without reference question and fixing already written stuff that is using references question.. Commented Jul 28, 2015 at 11:45
  • Your array makes no sense to me. Can you please try using valid PHP syntax in your example code? Commented Jul 28, 2015 at 11:46
  • ^ the better way is used var_export Commented Jul 28, 2015 at 11:47
  • @Sherif: Done, is this better? Commented Jul 28, 2015 at 12:07

1 Answer 1

1

Oooh, this kind of problems do tickle my fancy. So, here is my solution:

<?php

$origArray = array(
    array('content_id' => 1, 'sort_order' => 1, 'level' => 1),
    array('content_id' => 7, 'sort_order' => 2, 'level' => 2),
    array('content_id' => 4, 'sort_order' => 3, 'level' => 2),
    array('content_id' => 2, 'sort_order' => 4, 'level' => 3),
    array('content_id' => 3, 'sort_order' => 5, 'level' => 1),
    array('content_id' => 6, 'sort_order' => 6, 'level' => 1),
    array('content_id' => 5, 'sort_order' => 7, 'level' => 2),
);

function sortByOrder($a, $b) {
    if ($a['sort_order'] == $b['sort_order']) {
        return 0;
    }
    return ($a['sort_order'] < $b['sort_order']) ? -1 : 1;
}

function createHierarchicalArray($arr) {
    $result = array();
    foreach ($arr as $el) {
        $result = insertArrayElement($result, $el['content_id'], $el['level']);
    }
    return $result;
}

function insertArrayElement($array, $id, $level, $currentLevel = 1) {
    if ($level > $currentLevel) {
        $ids = array_keys($array);
        $currentId = end($ids);
        if (!isset($array[$currentId]['children'])) {
            $array[$currentId]['children'] = array();
        }
        $array[$currentId]['children'] = insertArrayElement($array[$currentId]['children'], $id, $level, $currentLevel + 1);
    } else {
        $array[$id] = array();
    }

    return $array;
}

// Could do without this, if the array is already sorted. Otherwise it's a necessary step.
uasort($origArray, 'sortByOrder');

$result = createHierarchicalArray($origArray);

var_dump($result);

Edit: Changed the code to incorporate the changes in the question.

Sign up to request clarification or add additional context in comments.

5 Comments

Sorry if I changed something that gave you problem, was hoping only visual representation got changed with my edits.
Nice work man, really fast! Is there a way to keep the other data from original elements put into new array? I mean, I would probably pass the id of element from original array to recursive function and then copy stuff from original array in that $array['$id] = array() line. Is there a better/safer way?
$currentKey should probably be $currentId. Also, how do we get rid of notice: "Only variables should be passed by reference"?
I'd pass the contents of the original array to the insertArrayElement function as well (probably as the fourth parameter) and change the $array[$id] = array(); line to $array[$id] = $el; (or whatever you decide to call the parameter). I've changed the $currentId = end(array_keys($array)); line to get rid of the reference passing notice.
Thank you again for quick and really clean solution.

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.