ksort produces wrong result when dealing with alphanumeric characters
Asked Answered
B

6

6
<?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?

Boris answered 24/3, 2012 at 16:7 Comment(9)
What would you consider the right result?Finnougrian
I need to get the index sorted based on ASCII-table order.Boris
Where would 10 go, between 1 and 2 or after 9?Finnougrian
@Finnougrian - According to ASCII order '10' can't be after '9', right? I got your point, but if ASCII order is what OP wants, fine.Gretagretal
10 isn't an ASCII character (it is two characters), so saying "ASCII order" doesn't make sense, hence asking for clarification.Finnougrian
@Finnougrian I have a set of strings. I want to store the frequency of each characters. So All index are single character. So there is no index '10'.Boris
@habeebperwad great, thanks for finally replying.Finnougrian
@habeebperwad you do know there's already a function in PHP that will a) count the character frequencies, and b) already be sorted in "ASCII order", right? -- count_chars()Finnougrian
@ salathe Actually, I am doing a bit complex thing. I have the following conditions. a)First letter of all the strings are capital letters. But the count function should be treat it as lowercase letter. b) all letters after space character is also capital letter.But the count function should be treat it as lowercase letter. and so on. so I can't use the function.Boris
R
11

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
Raymund answered 24/3, 2012 at 16:12 Comment(3)
+1 You're only person here who answered question "Why does ksort give wrong result?"Gretagretal
@Gretagretal You are right. Just giving solution may help to solve our problem. But won't help us to improve our programming skill.Boris
I can't wait for the followup question, "Why does ksort SORT_STRING give wrong result?" when his numeric keys get into multiple digits.Finnougrian
F
10

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');
Finnougrian answered 24/3, 2012 at 16:16 Comment(0)
M
1

Try ksort($a, SORT_STRING) to force string comparisons on the keys.

Maltose answered 24/3, 2012 at 16:11 Comment(0)
N
1

This will work:

<?php ksort($a,SORT_STRING); ?>

Checkout the other sort_flags here http://www.php.net/manual/es/function.sort.php

Cheers!

Neomineomycin answered 24/3, 2012 at 16:12 Comment(0)
G
0

ksort(array, sortingtype) sorts an associative array in ascending order, according to the keys, for a specified sorting type (sortingtype). But because sortingtype has a default value of SORT_REGULAR, when the keys have a combination of numbers and strings, that weid or unexpected behaviour occurs.

You must always remember to explicitly specify the sorting type, to avoid it confusing numbers with strings.

$a = array('a'=>'7833','d'=>'1297','c'=>'341','1'=>'67','b'=>'225','3'=>'24','2'=>'44','4'=>'22','0'=>'84');
ksort($a, SORT_STRING);
foreach ($a as $key => $val) {
    echo "$key = $val\n";
}

PHP documentation on ksort

Gensmer answered 22/10, 2018 at 17:50 Comment(0)
W
-2

See this page for an overview of the different sort functions in php: http://php.net/manual/en/array.sorting.php

If you want it sorted by key, then use asort(), which produces this output:

Array
(
    [4] => 22
    [3] => 24
    [2] => 44
    [1] => 67
    [0] => 84
    [b] => 225
    [c] => 341
    [d] => 1297
    [a] => 7833
)
Winnick answered 24/3, 2012 at 16:12 Comment(1)
That's not sorting the keys, that's sorting the values.Raymund

© 2022 - 2024 — McMap. All rights reserved.