Sorting Arrays by Sub Array Values using PHP

Multidimensional arrays are very handy for storing lots of data in one array variable opposed to creating and having to manage many individual array variables. For example, let's say we need to store all of our employee's data. Instead of creating many different arrays, one for each employee, we can simply create a multidimensional array, and store all of the employee's data within that.

Multidimensional Array that we will sort

  //Here is an example of a multidimensional array
  //We will use this for all of our sorting examples
  $employees = array(
    0 => array(
      'id'        => 13,
      'firstname' => 'Marky',
      'lastname'  => 'Mark'
    ),
    1 => array(
      'id'        => 3,
      'firstname' => 'Bobby',
      'lastname'  => 'Bob'
    ),
    2 => array(
      'id'        => 42,
      'firstname' => 'Jimmy',
      'lastname'  => 'Jim'
    )
  );

The problem with multidimensional arrays is that you can not sort them as easily as single dimension arrays. The standard "sort", "asort", "ksort", etc... don't work. A little more work is needed to sort the data. To do this, PHP provides us with a handy "usort" function.

Example sorting a Multi-dimensional Array using "usort"

  //For this example, we will sort our $employees array by "firstname"
 
  //Here is the function we will use to compare the two sub array values
  function sortByFirstname($a, $b) {
    return strcasecmp($a['firstname'], $b['firstname']);
  }
 
  //Call "usort" and pass it the name of our callback function
  usort($employees, 'sortByFirstname');
 
  //Print out the newly sorted $employees multidimensional array
  print_r($employees);
 
  /* Prints out
  Array
  (
    [0] => Array
        (
            [id] => 3
            [firstname] => Bobby
            [lastname] => Bob
        )
 
    [1] => Array
        (
            [id] => 42
            [firstname] => Jimmy
            [lastname] => Jim
        )
 
    [2] => Array
        (
            [id] => 13
            [firstname] => Marky
            [lastname] => Mark
        )
 
  )
 
  */

As you can see, "usort" works great. It takes the array as the first parameter and the function that you will use as the second parameter, then sorts the array.

Instead of using "usort", you could also use "array_multisort". There are different ways of using this method, but I will use an example that I think illustrates this in the easiest to understand form.

Sorting a Multi-dimensional Array using "array_multisort"

  //build a new array with the key and value
  foreach($employees as $key => $value) {
      //still going to sort by firstname
    $emp[$key] = $value['firstname'];
  }
 
  array_multisort($emp, SORT_ASC, $employees);
 
  print_r($employees);
 
  /* Prints Out
  Array
  (
    [0] => Array
        (
            [id] => 3
            [firstname] => Bobby
            [lastname] => Bob
        )
 
    [1] => Array
        (
            [id] => 42
            [firstname] => Jimmy
            [lastname] => Jim
        )
 
    [2] => Array
        (
            [id] => 13
            [firstname] => Marky
            [lastname] => Mark
        )
 
  )
  */

The problem with "usort" and "array_multisort"

"usort" and "array_multisort" are nice PHP functions, however, what if we also wanted to sort our employees by last name? Then later on, what if we wanted to sort them by id? What if we wanted to sort ascending and descending as well? As you can see, "usort" will force you to create many different comparative functions. One for sorting by last name ascending, one for sorting by last name descending, one for sorting by id ascending, etc... "array_multisort" would force you to create many loops of dummy arrays for each sort.

To fix this problem of having to create a unique callback comparison function for every possibility or dummy arrays for each sort, I came up with a way to sort multi-dimensional arrays by their sub values with only one function.

Sorting Multidimensional Arrays by Sub Array Values

  function sortBySubArrayValue(&$array, $key, $dir='asc') {
 
    $sorter=array();
    $rebuilt=array();
 
    //make sure we start at the beginning of $array
    reset($array);
 
    //loop through the $array and store the $key's value
    foreach($array as $ii => $value) {
      $sorter[$ii]=$value[$key];
    }
 
    //sort the built array of key values
    if ($dir == 'asc') asort($sorter);
    if ($dir == 'desc') arsort($sorter);
 
    //build the returning array and add the other values associated with the key
    foreach($sorter as $ii => $value) {
      $rebuilt[$ii]=$array[$ii];
    }
 
    //assign the rebuilt array to $array
    $array=$rebuilt;
  }
 
  //sort $employees by firstname
  sortBySubArrayValue($employees, 'firstname');
 
  print_r($employees);
 
  /* Prints out
  Array
  (
    [0] => Array
        (
            [id] => 3
            [firstname] => Bobby
            [lastname] => Bob
        )
 
    [1] => Array
        (
            [id] => 42
            [firstname] => Jimmy
            [lastname] => Jim
        )
 
    [2] => Array
        (
            [id] => 13
            [firstname] => Marky
            [lastname] => Mark
        )
 
  )
  */
 
  //sort $employees by id, descending
  sortBySubArrayValue($employees, 'id', 'desc');
  print_r($employees);
 
  /* Prints Out
  Array
  (
    [0] => Array
        (
            [id] => 42
            [firstname] => Jimmy
            [lastname] => Jim
        )
 
    [1] => Array
        (
            [id] => 13
            [firstname] => Marky
            [lastname] => Mark
        )
 
    [2] => Array
        (
            [id] => 3
            [firstname] => Bobby
            [lastname] => Bob
        )
 
  )
  */

Comments

Dear sirsit would be nice to sort a subarray with 2, 3 sortkeys.Is it possible?sincerely edi