Tools Blog Learn Quizzes Smile API Log In / Sign Up
Tools Blog Learn Quizzes Smile API Log In / Sign Up
« Return to the tutorials list
We have updated our privacy policy to let you know that we use cookies to personalise content and ads. We also use cookies to analyse our traffic and we share information about your use of our site and application with our advertising and analytics partners. By using this website or our application you agree to our use of cookies. Learn more about the way this website uses cookies or remove this message.

You can read this article in: English :: Español :: русский

3 solutions for sorting multidimensional arrays by child keys or values in PHP

January 29, 2017 Difficulty: 50 / 50 Tweet
sorted lego pieces

One of the tasks that less experienced programmers find really difficult is to sort multidimensional arrays by one of the values in the child arrays. In today's tutorial I'm going to show you 3 ways of achieving that - you decide which ones seems easier for you and provides the best performance.

Let's assume a scenario where we have a huge array like the one below and we need to sort it by a value contained in the last child array - in our case the value of the 'weight' key.

  
  <?php
  $array = [
              [
                ['name'=>'John B'],
                ['age'=>30],
                ['sizes'=>
                          [
                          'weight'=>80, 
                          'height'=>120
                          ]
                ]
              ],
              [
                ['name'=>'Marie B'],
                ['age'=>31],
                ['sizes'=>
                          [
                          'weight'=>60, 
                          'height'=>110
                          ]
                ]
              ],
              [
                ['name'=>'Carl M'],
                ['age'=>12],
                ['sizes'=>
                          [
                          'weight'=>70, 
                          'height'=>100
                          ]
                ]
              ],
              [
                ['name'=>'Mike N'],
                ['age'=>19],
                ['sizes'=>
                          [
                          'weight'=>70, 
                          'height'=>150
                          ]
                ]
              ],
              [
                ['name'=>'Nancy N'],
                ['age'=>15],
                ['sizes'=>
                          [
                          'weight'=>60, 
                          'height'=>150
                          ]
                ]
              ],
              [
                ['name'=>'Cory X'],
                ['age'=>15],
                ['sizes'=>
                          [
                          'weight'=>44, 
                          'height'=>150
                          ]
                ]
              ]
  ];
  ?>
  

Sorting method 1 - Using usort and a simple callback function (Recommended).

This is a really simple method - usort automatically loops through each combination of two elements of the array, compares whatever you want it to compare in the callback function, and by returning -1 or 1 respectively, it assigns the appropriate index to the given element in the resulting array. In our case, if the 'weight' in $a is smaller or equal than the 'weight' in $b, the content of $a will end up having a smaller index in the array to be ordered. Here's the code:


  <?php
  //Method1: sorting the array using the usort function and a "callback that you define"
  function method1($a,$b) 
  {
    return ($a[2]["sizes"]["weight"] <= $b[2]["sizes"]["weight"]) ? -1 : 1;
  }
  usort($array, "method1");
  print_r($array);
  ?>

The bubble method - or doing it the old school way

The bubble method is something people used to learn in computer science back in the 90s. It is known to be a slow method of reordering as it needs to loop through the array multiple times.

The bubble method checks each set of adjacent values and if the required condition is met it swaps their positions. This action is then performed again and again until no reordering is necessary in a full array traversal. In this example the array is traversed until all weights found at key $j are smaller than the weights found at $j+1. Have a look:


<?php
//Method 2: The bubble method
$j=0;
$flag = true;
$temp=0;

while ( $flag )
{
  $flag = false;
  for( $j=0;  $j < count($array)-1; $j++)
  {
    if ( $array[$j][2]["sizes"]["weight"] > $array[$j+1][2]["sizes"]["weight"] )
    {
      $temp = $array[$j];
      //swap the two between each other
      $array[$j] = $array[$j+1];
      $array[$j+1]=$temp;
      $flag = true; //show that a swap occurred
    }
  }
}
print_r($array);
?>

The do it yourself method

Some programmers simply prefer writing their own code for such tasks so I thought I would give you an example of custom code for achieving the same result.

The way I designed it is pretty straightforward:

First create a temporary empty array, then loop through the array that needs to be ordered and replace its existing keys with the values of what you are ordering by. Please note that you also need to make sure that the new keys are unique so you don't lose any elements. In my case - I decided to use the old keys and append them to the new ones so the resulting keys are something like: "new_key" . "some_string" . "old_unique_key". Then I sort the temporary array by key using the built in ksort() function and use array values to re-index the array numerically. Here's the code:

Please note that the code below will not work correctly in some cases. For example, if one 'weight' would be more than or equal to 100, then the ksort function would fail to give the right results. You can use ksort($temp, SORT_NATURAL) in such a case.


<?php
  //Method3: DIY 
  $temp = [];
  foreach ($array as $key => $value)
    $temp[$value[2]["sizes"]["weight"] . "oldkey" . $key] = $value; //concatenate something unique to make sure two equal weights don't overwrite each other
  ksort($temp); // or ksort($temp, SORT_NATURAL); see paragraph above to understand why
  $array = array_values($temp);
  unset($temp);
  print_r($array);
?>

Update: January 29th 2017 - The array_multisort() way...

Another option for sorting multi-dimensional arrays is to use a built in function called array_multisort(). While it can also be used to sort several independent arrays at once, its real power comes into play because it provides an off the shelf method to sort a multi-dimensional array by one or more "child" dimensions.

Combining array_multisort() with array_map() and its callback for obtaining an array of weights, allows for this complex sorting to happen in only one call.


  <?php
  array_multisort(array_map(function($element) {
      return $element[2]['sizes']['weight'];
  }, $array), SORT_ASC, $array);

Because this last method doesn't look as easy as the others... I will explain what it does:

  • array_map applies a callback function on each element of the input, thus generating a numerically indexed array of weights.
  • array_multisort reorders the array of weights and it also applies it to the input array.

Hope you liked today's tutorial.Thanks!

comments powered by Disqus

Better Docs For A Better Web - Mozilla Developer Network

Alerts

2017-07-25 - In all versions of PHP 7, during the unserialization process, resizing the 'properties' hash table of a serialized object may lead to use-after-free. A remote attacker may exploit this bug to gain arbitrary code execution. Read more ...
2017-07-25 - Off-by-one error in the phar_parse_pharfile function in ext/phar/phar.c in PHP before 5.6.30 and 7.0.x before 7.0.15 allows remote attackers to cause a denial of service (memory corruption) or possibly execute arbitrary code via a crafted PHAR archive with an alias mismatch. Read more ...

See All Entries...