http://www.perlmonks.org?node_id=814356

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

my %statistics = ( 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9, 0, 10, 0 ); foreach my $statistic (sort keys %statistics) { print $statistic ." ".$statistics{$statistic}. "\n"; }
Are keys always of type string? If not, why is 10 printed after 1 instead of 2? How do I sort as: 1,2,3...10. Thanks.

Replies are listed 'Best First'.
Re: Sorting integer value hash keys
by CountZero (Bishop) on Dec 25, 2009 at 16:38 UTC
    Because sort does an alphabetic sort by default. If you want to do a numerical sort, you must provide the sort routine yourself as a code block:
    sort {$a <=> $b} keys %statistics

    Try perldoc -f sort for more info.

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

Re: Sorting integer value hash keys
by gube (Parson) on Dec 25, 2009 at 18:08 UTC
    #!/usr/bin/perl my %statistics = ( 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9, 0, 10, 0 ); foreach my $statistic (sort {$a <=> $b} keys %statistics) { print $statistic ." ".$statistics{$statistic}. "\n"; } Output: 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 9 0 10 0
      Sorry, I can't resist:
      my %statistics; undef @statistics{ 1..10 }; # or @statistics{ 1..10 } = (0) x 10 say join "\n", sort { $a <=> $b } keys %statistics;
      or, if you don't need a name and like the 0 values:
      say join "\n", sort { $a <=> $b } keys %{{ map { $_ => 0 } 1..10 }}
        You're missing a newline on the last line.
        say join "\n", sort { $a <=> $b } keys %{{ map { $_ => 0 } 1..10 }}
        should becan be shortened to
        say for sort { $a <=> $b } keys %{{ map { $_ => 0 } 1..10 }}
        Furthermore, since you assume the list is constant, that can be simplified to
        say for sort { $a <=> $b } 1..10;
        And if you wanted to show that stringification doesn't matter, the following would suffice:
        say for sort { $a <=> $b } map "$_", 1..10;