Alphabetical sorting with PHP in a multidimensional array Posted by Mischa S.

Back

Date: April 3, 2013

A multidimensional sorting experiment was foisted upon me by having to sort a giant array of LDAP results coming from Active Directory.  Here is the weirdness in its rawest form.

Consider this array.  Seriously, consider this sucker!  Do it!

$arr = array(
		array(
			35,
			"name" => "Fred"
		),
		array(
			22,
			"name" => "Timmy"
		),
		
		array(
			78,
			"name" => "Dick"
		)
	);

If you try to sort it....

sort($arr);
var_dump($arr);

by default, it will sort by the number, not the name.

array(3) {
  [0]=>
  array(2) {
    [0]=>
    int(22)
    ["name"]=>
    string(5) "Timmy"
  }
  [1]=>
  array(2) {
    [0]=>
    int(35)
    ["name"]=>
    string(4) "Fred"
  }
  [2]=>
  array(2) {
    [0]=>
    int(78)
    ["name"]=>
    string(4) "Dick"
  }
}

Now, lets change the array up and make all the numbers the same value, like this:

$arr = array(
		array(
			1,
			"name" => "Fred"
		),
		array(
			1,
			"name" => "Timmy"
		),
				
		array(
			1,
			"name" => "Dick"
		)
	);

Sort and dump and we get:

array(3) {
  [0]=>
  array(2) {
    [0]=>
    int(1)
    ["name"]=>
    string(4) "Dick"
  }
  [1]=>
  array(2) {
    [0]=>
    int(1)
    ["name"]=>
    string(4) "Fred"
  }
  [2]=>
  array(2) {
    [0]=>
    int(1)
    ["name"]=>
    string(5) "Timmy"
  }
}

Hey!  That's what I wanted.  Well, I'll be a filthy animal.  I've done it.  So, I just loop through the ldap result set and remove or normalize all the variables immediately in front of the variable I care about.....oh wait, that's friggin' stupid.  OK, better idea!  usort()

usort($arr, function($a, $b) {
			return $a['name'] - $b['name']; 
        });
var_dump($arr);

yields us....

array(3) {
  [0]=>
  array(2) {
    [0]=>
    int(78)
    ["name"]=>
    string(4) "Dick"
  }
  [1]=>
  array(2) {
    [0]=>
    int(22)
    ["name"]=>
    string(5) "Timmy"
  }
  [2]=>
  array(2) {
    [0]=>
    int(35)
    ["name"]=>
    string(4) "Fred"
  }
}

Derp.  Oh wait....we're not dealing with numbers. /facepalm

So....not lets have some fun.

usort($arr, function($a, $b) {
			
          $a1 = $a["name"]; //get the name string value
          $b1 = $b["name"];
          
          $out = strcasecmp($a1,$b1);
          if($out == 0){ return 0;} //they are the same string, return 0
          if($out > 0){ return 1;} // $a1 is lower in the alphabet, return 1
          if($out < 0){ return -1;} //$a1 is higher in the alphabet, return -1
        });
var_dump($arr);

usort custom function plus strcasecmp() and now we got it.  strcasecmp compares the lexographical value of each string and returns difference in those values.  If the first value passed in (the custom function iterates) would come before the second word, if you were alphabetizing them, then it returns the difference in a negative integer.  If it would come after, you get a positive integer.  If it's the same word, you get zero.

I added the conditionals at the end, as the custom function only likes to receive 1, -1 or zero.  And now we have custom alphabetical sorting inside a multidimensional array based on a user defined key value.  I wish I could've done this in Coldfusion.