2

I have an array of arrays - each has own id and parent id values. I want to sort it so that every child should be beneath it's parent. Let me show You my code:

  1. Given Array:

    $arr = array(array('id' => 15, 'parent' => 12), 
    array('id' => 10, 'parent' => 12), 
    array('id' => 12, 'parent' => 12), 
    array('id' => 17, 'parent' => 12), 
    array('id' => 21, 'parent' => 15), 
    array('id' => 13, 'parent' => 15), 
    array('id' => 15, 'parent' => 15), 
    array('id' => 25, 'parent' => 15), 
    array('id' => 7, 'parent' => 7), 
    array('id' => 18, 'parent' => 7), 
    array('id' => 4, 'parent' => 7), 
    array('id' => 1, 'parent' => 3), 
    array('id' => 5, 'parent' => 5), 
    array('id' => 2, 'parent' => 7));
    
  2. How the output should looki like (asc by parents, every children also ascending - always under parent (parent always as first)):

          0 =>
              'id' => int 1
              'parent' => int 3
          1 =>
              'id' => int 5
              'parent' => int 5
          2 =>
              'id' => int 7
              'parent' => int 7
          3 =>
              'id' => int 2
              'parent' => int 7
          4 =>
              'id' => int 4
              'parent' => int 7
          5 =>
              'id' => int 18
              'parent' => int 7
          6 =>
              'id' => int 12
              'parent' => int 12
          7 =>
              'id' => int 10
              'parent' => int 12
          8 =>
              'id' => int 15
              'parent' => int 12
          9 =>
              'id' => int 17
              'parent' => int 12
          10 =>
              'id' => int 15
              'parent' => int 15
          11 =>
              'id' => int 13
              'parent' => int 15
          12 =>
              'id' => int 21
              'parent' => int 15
          13 =>
              'id' => int 25
              'parent' => int 15
    
  3. Question: I'am wondering what is the easiest solution to achieve this ? I've managed to do that, but I cant stop the feeling that there is a way to do that in quicker and more optimal way..

  4. Here is my code:

    function groupByParent ($array)
    {
        $groups = array();
        foreach ($array as $a) {
            $groups[$a['parent']][] = $a;
        }
        return $groups;
    }
    function insideSort ($array)
    {
        foreach ($array as $k => $v) {
            usort($array[$k], function($a, $b){
               return $a['id'] == $b['parent'] ? -1 : 1;
            });
            $f = array_shift($array[$k]);
            sort($array[$k]);
            array_unshift($array[$k], $f);
        }
        return $array;
    }
    function finalSort($array)
    {
        $final = array();
        foreach ($array as $a) {
            $final = array_merge($final, $a);
        }
        return $final;
    }
    
    $grr = groupByParent($arr);
    $irr = insideSort($grr);
    ksort($irr);
    $res = finalSort($irr);
    
  5. Is there easier way to achieve it ?

Cheers

0

2 Answers 2

1

You can use array_multisort along with array_column:

array_multisort(
    array_column($arr, 'parent'),
    array_column($arr, 'id'),
    $arr
);

Here is working demo.

I guess this is the simplest and the most right way to do, as array_multisort was created for such cases.

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

1 Comment

not working - parents arent always on top of their children
0

You want to look in to usort to sort an array by values using a user-defined comparison function

<?php
$arr = [
    ['id' => 15, 'parent' => 12],
    ['id' => 10, 'parent' => 12],
    ['id' => 12, 'parent' => 12],
    ['id' => 17, 'parent' => 12],
    ['id' => 21, 'parent' => 15],
    ['id' => 13, 'parent' => 15],
    ['id' => 15, 'parent' => 15],
    ['id' => 25, 'parent' => 15],
    ['id' => 7, 'parent' => 7],
    ['id' => 18, 'parent' => 7],
    ['id' => 4, 'parent' => 7],
    ['id' => 1, 'parent' => 3],
    ['id' => 5, 'parent' => 5],
    ['id' => 2, 'parent' => 7],
];
usort(
    $arr,
    function ($a, $b) {
        if ($a['parent'] == $b['parent']) {
            if ($a['id'] == $b['id']) {
                return 0;
            }

            return ($a['id'] < $b['id']) ? -1 : 1;
        }

        return ($a['parent'] < $b['parent']) ? -1 : 1;
    }
);
var_dump($arr);

This outputs

array(14) {
  [11]=>
  array(2) {
    ["id"]=>
    int(1)
    ["parent"]=>
    int(3)
  }
  [12]=>
  array(2) {
    ["id"]=>
    int(5)
    ["parent"]=>
    int(5)
  }
  [13]=>
  array(2) {
    ["id"]=>
    int(2)
    ["parent"]=>
    int(7)
  }
  [10]=>
  array(2) {
    ["id"]=>
    int(4)
    ["parent"]=>
    int(7)
  }
  [8]=>
  array(2) {
    ["id"]=>
    int(7)
    ["parent"]=>
    int(7)
  }
  [9]=>
  array(2) {
    ["id"]=>
    int(18)
    ["parent"]=>
    int(7)
  }
  [1]=>
  array(2) {
    ["id"]=>
    int(10)
    ["parent"]=>
    int(12)
  }
  [2]=>
  array(2) {
    ["id"]=>
    int(12)
    ["parent"]=>
    int(12)
  }
  [0]=>
  array(2) {
    ["id"]=>
    int(15)
    ["parent"]=>
    int(12)
  }
  [3]=>
  array(2) {
    ["id"]=>
    int(17)
    ["parent"]=>
    int(12)
  }
  [5]=>
  array(2) {
    ["id"]=>
    int(13)
    ["parent"]=>
    int(15)
  }
  [6]=>
  array(2) {
    ["id"]=>
    int(15)
    ["parent"]=>
    int(15)
  }
  [4]=>
  array(2) {
    ["id"]=>
    int(21)
    ["parent"]=>
    int(15)
  }
  [7]=>
  array(2) {
    ["id"]=>
    int(25)
    ["parent"]=>
    int(15)
  }
}
➜  promote-api git:(develop) ✗ php test.php
array(14) {
  [0]=>
  array(2) {
    ["id"]=>
    int(1)
    ["parent"]=>
    int(3)
  }
  [1]=>
  array(2) {
    ["id"]=>
    int(5)
    ["parent"]=>
    int(5)
  }
  [2]=>
  array(2) {
    ["id"]=>
    int(2)
    ["parent"]=>
    int(7)
  }
  [3]=>
  array(2) {
    ["id"]=>
    int(4)
    ["parent"]=>
    int(7)
  }
  [4]=>
  array(2) {
    ["id"]=>
    int(7)
    ["parent"]=>
    int(7)
  }
  [5]=>
  array(2) {
    ["id"]=>
    int(18)
    ["parent"]=>
    int(7)
  }
  [6]=>
  array(2) {
    ["id"]=>
    int(10)
    ["parent"]=>
    int(12)
  }
  [7]=>
  array(2) {
    ["id"]=>
    int(12)
    ["parent"]=>
    int(12)
  }
  [8]=>
  array(2) {
    ["id"]=>
    int(15)
    ["parent"]=>
    int(12)
  }
  [9]=>
  array(2) {
    ["id"]=>
    int(17)
    ["parent"]=>
    int(12)
  }
  [10]=>
  array(2) {
    ["id"]=>
    int(13)
    ["parent"]=>
    int(15)
  }
  [11]=>
  array(2) {
    ["id"]=>
    int(15)
    ["parent"]=>
    int(15)
  }
  [12]=>
  array(2) {
    ["id"]=>
    int(21)
    ["parent"]=>
    int(15)
  }
  [13]=>
  array(2) {
    ["id"]=>
    int(25)
    ["parent"]=>
    int(15)
  }
}

1 Comment

as above - not working - parents arent always on top of their children

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.