Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ksort produces wrong result when dealing with alphanumeric characters

Tags:

php

sorting

ksort

<?php

    $a = array(
        'a'=>'7833',
        'd'=>'1297',
        'c'=>'341',
        '1'=>'67',
        'b'=>'225',
        '3'=>'24',
        '2'=>'44',
        '4'=>'22',
        '0'=>'84'
    );

    ksort($a);

    print_r($a);

The above code produces the following output.

Array
(
    [0] => 84
    [a] => 7833
    [b] => 225
    [c] => 341
    [d] => 1297
    [1] => 67
    [2] => 44
    [3] => 24
    [4] => 22
)

Why does ksort give wrong result?

like image 956
Mohammed H Avatar asked Mar 24 '12 16:03

Mohammed H


2 Answers

You'll want to use the SORT_STRING flag. SORT_REGULAR would compare items with their current types, in which case the number 1 does come after the string 'a':

php -r "echo 1 > 'a' ? 'yes' : 'no';" // yes
like image 178
Andrew Kandels Avatar answered Sep 30 '22 06:09

Andrew Kandels


The default sorting uses SORT_REGULAR.

This takes the values and compares them as described on the comparison operators manual page. For the times when the string keys, in your example, are compared with zero; those strings are converted to numbers (all 0) for comparision. If two members compare as equal, their relative order in the sorted array is undefined. (Quoted from usort() manual page.)

If you want the sorted output to have numbers before letters, you should use SORT_NATURAL as of PHP 5.4. SORT_STRING will also do the job only if the numbers remain single digits.

SORT_NATURAL (PHP 5.4 or above) gives keys ordered as:

0,1,2,4,11,a,b,c

SORT_STRING gives keys ordered as:

0,1,11,2,4,a,b,c

An alternative to SORT_NATURAL for PHP less than 5.4, would be use uksort().

uksort($a, 'strnatcmp');
like image 23
salathe Avatar answered Sep 30 '22 06:09

salathe