0

I have an external API that returns a category list:

Current array:

id | parent | name
3  | 6      | Sub
6  | 9      | Test
9  | 0      | Parent 1
2  | 0      | Parent 2

Need to be:

id | parent | name
9  | 0      | Parent 1
2  | 0      | Parent 2
6  | 9      | Test
3  | 6      | Sub

Now I will convert this list in the right order, (from parent to childs), so I can simple foreach this new array and insert it in my database (with my custom parent_id).

I have created a function, but this works not good:

// DOES NOT WORK!!
function sortArrayFromParentToChilds($array)
{
    $output = [];
    foreach ($array as $key => $a) {

        // search in new array
        if (empty($output)) {
            $output[] = $a;
            unset($array[$key]);
        } else {

            if (findSubCategory($a, $output)) {
                array_push($output, $a);
            } else {
                array_unshift($output, $a);
            }
            unset($array[$key]);
        }


    }
    return $output;
}
function findSubCategory($id, $output)
{
    foreach ($output as $o) {
        if ($o['parent'] == $id) {
            return true;
        }
    }
    return false;
}

$result = sortArrayFromParentToChilds($initial);

Who can help me to get this function working?

Updated: added some sample data:

$initial = array(
    array(
        'name' => 'Paul',
        'id' => 4,
        'parent' => 2
    ),
    array(
        'name' => 'Liz',
        'id' => 5,
        'parent' => 2
    ),
    array(
        'name' => 'Comus',
        'id' => 6,
        'parent' => 3
    ),
    array(
        'name' => 'Mai',
        'id' => 7,
        'parent' => 2
    ),
    array(
        'name' => 'Titus',
        'id' => 8,
        'parent' => 3
    ),
    array(
        'name' => 'Adult',
        'id' => 9,
        'parent' => 6
    ),
    array(
        'name' => 'People',
        'id' => 2,
        'parent' => 0
    ),
    array(
        'name' => 'Puppy',
        'id' => 10,
        'parent' => 8
    ),
    array(
        'name' => 'Programmers',
        'id' => 11,
        'parent' => 4
    ),
);
4
  • 1
    What should the resulting array look like and what is the result of your function? Commented May 19, 2021 at 14:56
  • i have updated my question with the desired result! Commented May 19, 2021 at 15:03
  • If the only purpose of reordering is to insert it in a specific order in the database, there is no need for it. You can always retrieve from the database with ORDER BY Commented May 19, 2021 at 15:21
  • The "array" shown doesn't look like an array. Can you show it as it appears in code, or with var_export, please? Commented May 19, 2021 at 15:38

2 Answers 2

1

This solution looks for all elements that have no parents, stores them in the $sortArray and deletes them in $data.

$data = $initial;

$sortData = [];
while(count($data)){
  $ids = array_column($data,'id');
  foreach($data as $key => $row){
    if(in_array($row['parent'],$ids)) continue;
    $sortData[] = $row;
    unset($data[$key]);
  }
}

echo '<pre>';
var_export($sortData);

Output:

array (
  0 => 
  array (
    'name' => 'Comus',
    'id' => 6,
    'parent' => 3,
  ),
  1 => 
  array (
    'name' => 'Titus',
    'id' => 8,
    'parent' => 3,
  ),
  2 => 
  array (
    'name' => 'People',
    'id' => 2,
    'parent' => 0,
  ),
  3 => 
  array (
    'name' => 'Paul',
    'id' => 4,
    'parent' => 2,
  ),
  4 => 
  array (
    'name' => 'Liz',
    'id' => 5,
    'parent' => 2,
  ),
  5 => 
  array (
    'name' => 'Mai',
    'id' => 7,
    'parent' => 2,
  ),
  6 => 
  array (
    'name' => 'Adult',
    'id' => 9,
    'parent' => 6,
  ),
  7 => 
  array (
    'name' => 'Puppy',
    'id' => 10,
    'parent' => 8,
  ),
  8 => 
  array (
    'name' => 'Programmers',
    'id' => 11,
    'parent' => 4,
  ),
) 

Note: There must be no elements with id == parent in $data.

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

1 Comment

This is exactly what I need. Thanks very much!!
1

This should work.

function orderArray($arr){

    $ordArr = array();
    $parentKeys = array(0); // Top Level elements have 0 in parent field
    $newParentKeys = array();
    $goon = true;

    // search for parentkeys
    while($goon) {
        $goon = false;
        foreach($arr as $row) {
            if (in_array( $row['parent'], $parentKeys)){ // There are kids
                $newParentKeys[] = $row['id']; // future parent key
                $ordArray[] = $row; // add element in order
                $goon = true; // Keep going another level down
            }
        }
        $parentKeys = $newParentKeys; // Update parent keys for the next level
        $newParentKeys = array(); // clear this array

    }

    return $ordArray;
}

3 Comments

Sorry, it doesn't work. I have add some sample data to my original post, when I insert this data, it doesnt work...
Id 3 is missing in your sample data. So children of this ID (6, 8) and subsequent children (9, 10) will not be listed. I assumed only parent = 0 to start tree traversal.
I rated the approach as good. The initial dates were so that only parent == 0 have no parents.

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.