PHP: sort an array by key case-insensitive

In some situations one wants to sort an array by key but PHP’s ksort() function sorts case-sensitive which is not always what you want. The result of ksort is an order like A < C < b instead of A < b < C. With the next snippet I show you a concrete example by executing the necessary php code (in the command line interface).

# php -r '$arr=array("C"=>3,"b"=>2,"A"=>1); ksort($arr); print_r($arr);'
Array
(
    [A] => 1
    [C] => 3
    [b] => 2
)

In PHP 5.4.0 the flag SORT_FLAG_CASE has been introduced for exact this purpose, sorting strings case-insensitively. Unfortunately PHP 5.2.x and 5.3.x are still most used versions which require a custom solution to make the code compatible with older versions.

The first solution I had in mind was to create a map with the lower-case keys referencing the original case-sensitive keys which I then sort (by key of course). At this point we have the order we want, next two steps are creating a new array with the original key-value pair and writing it assigning it to the passed array reference.

class Utils
{
    /**
     * Sorts an array by key case-insensitive, maintaining key to data correlations.
     * This is useful mainly for associative arrays.
     * 
     * @param array $array_arg Array to be sorted by key case-insensitive
     */
    public static function ksort(&$array_arg)
    {
        $key_map = array();
        
        // create a map with keys in lower case referencing the case-sensitive keys
        foreach($array_arg as $key => $value)
            $key_map[strtolower($key)] = $key;
            
        // sort by the (lowercase) keys
        ksort($key_map);
        
        $ret_array = array();
        
        foreach($key_map as $lower_key => $original_key)
            $ret_array[$original_key] = $array_arg[$original_key];
        
        $array_arg = $ret_array;
    }
}

Now the output is exactly what we wanted.

# php -r 'include("Utils.class.php"); $arr=array("C"=>3,"b"=>2,"A"=>1); Utils::ksort($arr); print_r($arr);'
Array
(
    [A] => 1
    [b] => 2
    [C] => 3
)

After little research I came across other sorting functions as listed in the next table.

Function name Sorts by Maintains key association Order of sort Related functions
array_multisort() value associative yes, numeric no first array or sort options array_walk()
asort() value yes low to high arsort()
arsort() value yes high to low asort()
krsort() key yes high to low ksort()
ksort() key yes low to high asort()
natcasesort() value yes natural, case insensitive natsort()
natsort() value yes natural natcasesort()
rsort() value no high to low sort()
shuffle() value no random array_rand()
sort() value no low to high rsort()
uasort() value yes user defined uksort()
uksort() key yes user defined uasort()
usort() value no user defined uasort()

We see that only three functions consider the keys when sorting an array.

  • ksort — sort by key
  • krsort — sort by key in reverse order
  • uksort — sort by key using a user-supplied comparison function

Alternatively to the solution above we can use uksort which leads to a shorter implementation.

class Utils
{
    /**
     * Sorts an array by key case-insensitive, maintaining key to data correlations. 
     * This is useful mainly for associative arrays.
     * 
     * @param array $array_arg Array to be sorted by key case-insensitive
     */
    public static function ksort(&$array_arg)
    {        
        function _strcmp($a, $b)
        {
            return strcasecmp($a, $b);
        }
        
        uksort($array_arg, "_strcmp");
    }
}

_strcmp, with a prepended underscore to avoid a conflict with PHP’s strcmp function, compares two strings and returns true if the first argument is alphanumerical smaller than the second argument while neglecting the letter case. uksort is expecting two arguments, the array to be sorted and our user-defined compare function. This produces the same result as with the previous implementation.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>