Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling

Sort hash keys

by cristianro87 (Initiate)
on Mar 18, 2014 at 17:10 UTC ( #1078817=perlquestion: print w/replies, xml ) Need Help??
cristianro87 has asked for the wisdom of the Perl Monks concerning the following question:

I have a hash with keys like this hs1 hs2 hs3 hs4 ... hs13 ... hs21 .. hsX i try to do

for my $nombre (sort keys %cuantas_veces_sale)

but i get this output hs1 hs10 hs11 and what i whant is this hs1 hs2 hs3 ... hs10 hs11 .. hsX

Replies are listed 'Best First'.
Re: Sort hash keys
by VincentK (Beadle) on Mar 18, 2014 at 18:16 UTC
    Hi cristianro87

    For something like this , I would use the Sort::Naturally library.

    Here is a sample of the sort, along with the output.

    use strict; use warnings; use Sort::Naturally; my %DATA_HASH = ( 'hs1' => 1, 'hs2' => 1, 'hs3' => 1, 'hs10' => 1, 'hs9' => 1, 'hs15' => 1, 'hs21' => 1, 'hs110' => 1, 'hs11' => 1 ); print "$_\n" foreach nsort keys %DATA_HASH; __END__ Output: C:\monks\sort>perl hs1 hs2 hs3 hs9 hs10 hs11 hs15 hs21 hs110 C:\monks\sort>
      FYI, there seem to be a couple bugs related to floats, negative integers, and text/number combos.
Re: Sort hash keys
by kennethk (Abbot) on Mar 18, 2014 at 17:20 UTC
    So, your issue is that you have a number preceded by alphabetic characters, and you want to do numeric sorting on the numbers? In your sample, all your keys begin with hs. Is this guaranteed? Also, what is this %planets hash? Essentially, if you want to sort based on a substring of your key, then you will need to parse out that substring.

    The easiest answer here would probably be to keep leading 0's on your keys, e.g. hs01 instead of hs1. Barring that, you could do the parsing in a named sub:

    use strict; my %planets; my %cuantas_veces_sale; for my $nombre (sort keysort keys %cuantas_veces_sale) { print "$nombre\n"; }; sub keysort { return $planets{$a} <=> $planets{$b} if $planets{$a} <=> $planets{ +$b}; my ($num_a) = $a =~ /(\d+)/; my ($num_b) = $b =~ /(\d+)/; $num_a <=> $num_b; }
    or possibly cache the parse in a hash ahead of time:
    use strict; my %planets; my %cuantas_veces_sale; my %alphas = map {$_ => /(\D+)/} keys %cuantas_veces_sale; my %numerics = map {$_ => /(\d+)/} keys %cuantas_veces_sale; for my $nombre (sort { $planets{$a} <=> $planets{$b} or $alphas{$a} cmp $alphas{$b} or $numerics{$a} cmp $numerics{$b} } keys %cuant +as_veces_sale) { print "$nombre\n"; };

    #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

      I updated the code, the planets things was just a test and i copy the wrong code. Yes hs is always there, and i can't put hs01 or whatever it must be hs1, hs2 and so on

Re: Sort hash keys
by Eily (Priest) on Mar 18, 2014 at 17:25 UTC

    cmp uses alphabetical order, you want numerical order on the number alone. One simple solution would be to have a function to extract the number out of the key and do : @sortedKeys = sort { $planets{$a} <=> $planets{$b} or getNum($a) <=> getNum($b) } keys %cuantas_veces_sale;

    This not the most effective solution, but it works well enough. To get the number inside the string you can use a regex like /(\d+)/, tr/// or substr depending on what you find the easier. The last two are perhaps more user-friendly, but require that your keys have a consistant format ("hs" and then the number for exemple).

Re: Sort hash keys
by LanX (Chancellor) on Mar 18, 2014 at 17:13 UTC
    I suppose you want

     for my $nombre (sort { $a cmp $b or $planets{$a} <=> $planets{$b}  } keys %cuantas_veces_sale)

    Though you haven't been clear what %planet holds.

    Cheers Rolf

    ( addicted to the Perl Programming Language)

      I updated the code, the planets things was just a test and i copy the wrong code

        > I updated the code, the planets things was just a test and i copy the wrong code

        please see How do I post a question effectively? and How (Not) To Ask A Question to avoid wasting our time.

        in this special case numeric sort works

        DB<106> sort {$a <=> $b } @keys => ( "hs5", "hs6", "hs7", "hs8", "hs9", "hs10", "hs11", "hs12", "hs13", "hs14", "hs15", )

        Cheers Rolf

        ( addicted to the Perl Programming Language)

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1078817]
Approved by Bloodnok
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others imbibing at the Monastery: (4)
As of 2016-09-25 23:23 GMT
Find Nodes?
    Voting Booth?
    Extraterrestrials haven't visited the Earth yet because:

    Results (474 votes). Check out past polls.