4

Trying to sort this array of objects according to (1) depth and (2) weight, and am unsure how to modify the function I'm using to include this other level...

I'm using this function:

function cmp( $a, $b ) {
    if(  $a->weight ==  $b->weight ){
        return 0 ;
    }
    return ($a->weight < $b->weight) ? -1 : 1;
}

And then doing this:

$menu = get_tree(4, $tid, -1, 2);
usort($menu, 'cmp');

And that will accurately sort the array according to weight, but I need to add in another level of sorting. So that the array is first sorted according to depth, and then by weight.

So that, if the original array looks like this:

    Array
(
    [0] => stdClass Object
        (
            [tid] => 24
            [name] => Sample
            [weight] => 3
            [depth] => 0
        )

    [1] => stdClass Object
        (
            [tid] => 66
            [name] => Sample Subcategory
            [weight] => 0
            [depth] => 1
        )

    [2] => stdClass Object
        (
            [tid] => 67
            [name] => Another Example
            [weight] => 1
            [depth] => 0
        )

    [3] => stdClass Object
        (
            [tid] => 68
            [name] => Subcategory for Another Example
            [weight] => 1
            [depth] => 1
        )

    [4] => stdClass Object
        (
            [tid] => 22
            [name] => A third example master category
            [weight] => 0
            [depth] => 0
        )

I can sort it first by depth, then by weight so that the result looks like this:

Array
(
    [0] => stdClass Object
        (
            [tid] => 22
            [name] => A third example master category
            [weight] => 0
            [depth] => 0
        )

    [1] => stdClass Object
        (
            [tid] => 67
            [name] => Another Example
            [weight] => 1
            [depth] => 0
        )

    [2] => stdClass Object
        (
            [tid] => 24
            [name] => Sample
            [weight] => 3
            [depth] => 0
        )

    [3] => stdClass Object
        (
            [tid] => 66
            [name] => Sample Subcategory
            [weight] => 0
            [depth] => 1
        )

    [4] => stdClass Object
        (
            [tid] => 68
            [name] => Subcategory for Another Example
            [weight] => 1
            [depth] => 1
        )

3 Answers 3

9
function cmp( $a, $b )
{
  if ($a->depth == $b->depth)
  {
    if($a->weight == $b->weight) return 0 ;
    return ($a->weight < $b->weight) ? -1 : 1;
  }
  else
    return ($a->depth < $b->depth) ? -1 : 1;
}
Sign up to request clarification or add additional context in comments.

Comments

3

when comparing numbers, you can simply subtract them

function cmp($a, $b) {
   $d = $a->depth - $b->depth;
   return $d ? $d : $a->weight - $b->weight;
}

Comments

0

PHP has made great improvements since the year 2010. For this task, the PHP7 "spaceship operator" or "three-way comparison operator" can be used to craft a one-line comparison in the usort() call.

Code: (Demo)

usort($menu, function($a, $b) {
    return [$a->depth, $a->weight] <=> [$b->depth, $b->weight];
});

Output:

array (
  0 => 
  (object) array(
     'tid' => 22,
     'name' => 'A third example master category',
     'weight' => 0,
     'depth' => 0,
  ),
  1 => 
  (object) array(
     'tid' => 67,
     'name' => 'Another Example',
     'weight' => 1,
     'depth' => 0,
  ),
  2 => 
  (object) array(
     'tid' => 24,
     'name' => 'Sample',
     'weight' => 3,
     'depth' => 0,
  ),
  3 => 
  (object) array(
     'tid' => 66,
     'name' => 'Sample Subcategory',
     'weight' => 0,
     'depth' => 1,
  ),
  4 => 
  (object) array(
     'tid' => 68,
     'name' => 'Subcategory for Another Example',
     'weight' => 1,
     'depth' => 1,
  ),
)

Writing $a properties in the left array and $b properties on the right will sort ASC; reverse these respective positions to use DESC directional sorting.

Extension: If you want to sort by: $weight DESC, then $name ASC, then $depth DESC, write the array of comparison criteria like this:

[$b->weight, $a->name, $b->depth] <=> [$a->weight, $b->name, $a->depth]

From PHP7.2, another technique can be used: array_multisort() and multiple calls of array_column(). Before 7.2, array_column() could not be used on objects.)

Code: (Demo)

array_multisort(array_column($menu, 'depth'), array_column($menu, 'weight'), $menu);

To mirror the criteria in my earlier "Extension", the syntax gets a bit longer because each column requires its own array_column() call and sorting directions need to be expressed.

array_multisort(array_column($menu, 'weight'), SORT_DESC, array_column($menu, 'name'), array_column($menu, 'depth'), SORT_DESC, $menu);

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.