Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

foreach (reverse sort {$one{$a} cmp $one{$b} || $a cmp $b} (keys %one) +)
This sorts like:
4 3 2 14 13
Instead of
14 13 4 3 2
How can I fix this?

Replies are listed 'Best First'.
Re: Sorting sorts 13 as less than 2
by rafl (Friar) on Mar 22, 2006 at 00:17 UTC

    You're doing an alphabetical sort. Sort numerically using

    @sorted = sort { $a <=> $b } @unsorted;

    See the perlop manpage for details.

    Cheers, Flo

Re: Sorting sorts 13 as less than 2
by merlyn (Sage) on Mar 22, 2006 at 00:17 UTC

      Though the title is quite leading, the OP didn't tell us much about values %one.

      Without knowing about that side, we can't tell if that value comparision should be part of the sort function at all or if a switch in that part from cmp to <=> is advisable...

      H:\perl>perl my %one = ( 4 => 1, 3 => 2, 2 => 3, 14 => 4, 13 => 5, ); my @result = reverse sort { $one{$b} <=> $one{$a} or $b <=> $a } keys +%one; print join $/ => @result; ^Z 4 3 2 14 13

      ;-)

Re: Sorting sorts 13 as less than 2
by davido (Cardinal) on Mar 22, 2006 at 05:39 UTC

    cmp compairs strings. Consider for a moment a comparison of the string 'b' with 'ac'. Which string comes first in ascending order? That's easy; 'ac' comes first because 'a' is less than 'b'.

    Now look at '4' and '13' as strings. The string on the left contains a single character; '4'. The string on the right contains two characters, '1' and '3'. The leftmost character (1) is compared to the only character in the other string (4), and since 1 is less than 4, the string with the digits '1' and '3' (13) is positioned closer to the start of an ascending order list than the string with only a '4' in it. When doing a string comparison, you're not comparing the number 13 with the number 4. You're comparing the string containing a 1 and a 3 with the string containing only a 4.

    This behavior is sometimes casually referred to as "ASCIIbetical sorting", because it's not strictly alphabetical, and not exactly the way a dictionary works, but does make sense in the context of a given character set. One big difference between asciibetical sorting and alphabetical sorting is that with true alphabetical sorting 'A' and 'a' would be right next to each other in priority instead of being separated by B-Z and a few other symbols.


    Dave