PHP sort array keys by alphabetically and then numerically

4.4k Views Asked by At

I am trying to sort an array (with both alphabetic and numeric keys) by keys where the alphabetic keys will come first alphabetically and then numeric keys numerically.

Tried ksort with all the available flags, however that didn't help. Tried several SO answers, but none of them served my purpose. Here is an example of the the array I have..

$array = array(
    'Bat' => array(),
    'Dog' => array(),
    'Apple' => array(),
    'Cat' => array(),
    1 => array(),
    3 => array(),
    2 => array(),
    4 => array()
);  

I need to sort it like this:

$array = array(
    'Apple' => array(),
    'Bat' => array(),
    'Cat' => array(),
    'Dog' => array(),
    0 => array(),
    1 => array(),
    2 => array(),
    3 => array()
);  

What I understand from a SO answer that it might need a custom function to sort using the usort function. That's where I am lost. Any help or guide to the proper direction will be appreciated.

Thanks

4

There are 4 best solutions below

0
Abhik On

Please don't mind the question. I have managed achieve bu using a custom function. I am posting the answer here to help if someone faces this issue.

function ev_sort_array( $array ) {
    $alp = array();
    $num = array();
    foreach ( $array as $key => $value ) {
        if ( is_numeric($key) ) {
            $num[$key] = $value;
        } else {
            $alp[$key] = $value;
        }
    }
    ksort( $alp );
    ksort( $num );

    return array_merge( $alp, $num );
}  

Thanks

0
Elementary On

You can use uksort this way:

$array = array(
'Bat' => array(),
'Dog' => array(),
'Apple' => array(),
'Cat' => array(),
1 => array(),
3 => array(),
2 => array(),
4 => array()
); 
uksort($array,function($a,$b){
    if(is_int($a)&&is_int($b)) return $a-$b;
    if(is_int($a)&&!is_int($b)) return 1;
    if(!is_int($a)&&is_int($b)) return -1;
    return strnatcasecmp($a,$b);
});
print_r($array);

the output is as expected:

Array
(
    [Apple] => Array
        (
        )

    [Bat] => Array
        (
        )

    [Cat] => Array
        (
        )

    [Dog] => Array
        (
        )

    [1] => Array
        (
        )

    [2] => Array
        (
        )

    [3] => Array
        (
        )

    [4] => Array
        (
        )

)
6
splash58 On

If you use only english alphabet and digits, usual ksort function works fine

ksort($array);
print_r($array);

demo

2
mickmackusa On

As @splash58 states, ksort() is all that is required.

That said, if your project data is ordering numeric data before alphabetical and you need to reverse the order of those groups...

uksort() is the most direct/appropriate function for this job.

*Choose your key evaluating function carefully:

  • is_numeric() has a broad definition of what qualifies as true -- see the manual.
  • is_int() (and its alias is_integer()) is very strict in checking the data type. Importantly, a string key like "1" will evaluate to false.
  • ctype_digit(), while requiring all characters to be numeric, does not work on non-string type values. Importantly, a non-string key like 8 will evaluate to false.

If you are using php7, you can make good use the spaceship operator (<=>). If your php version is sub-7, you can use whatever old-skool comparison you like.

My solution allows the spaceship operator to order non-integers before integers, then sort those values ASC.

Code: (Demo)

$array = [
    2 => [],
    'Bat' => [],
    'Dog' => [],
    12 => [],
    'être' => [],
    'Cat' => [],
    1 => [],
    3 => [],
    'Apple' => [],
    4 => []
];

uksort($array, function ($a, $b) {
    return [is_int($a), $a] <=> [is_int($b), $b];
});

var_export($array);

The is_int() calls will return true or false. These are respectively compared as 1 and 0. Since sorting ASC, this means that false evaluations will come before true evaluations.

Output: (exactly the same as ksort())