Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

How to sort hash tables alpha-numeric

by juo (Curate)
on Oct 18, 2003 at 05:27 UTC ( #300236=perlquestion: print w/ replies, xml ) Need Help??
juo has asked for the wisdom of the Perl Monks concerning the following question:

$keys{'C10'}->{'C10-1'}=1; $keys{'C10'}->{'C10-2'}=1; $keys{'C10'}->{'C10-20'}=1; $keys{'C10'}->{'C10-3'}=1; $keys{'C200'}->{'C200-1'}=1; $keys{'C200'}->{'C200-20'}=1; $keys{'C200'}->{'C200-3'}=1; $keys{'C200'}->{'C200-21'}=1; $keys{'C30'}->{'C30-1'}=1; $keys{'C30'}->{'C30-2'}=1; $keys{'C30'}->{'C30-30'}=1; $keys{'C30'}->{'C30-4'}=1; # Result should be : 'C10' => HASH(0x1832a58) 'C10-1' => 1 'C10-2' => 1 'C10-3' => 1 'C10-20' => 1 'C30' => HASH(0x1832b30) 'C30-1' => 1 'C30-2' => 1 'C30-4' => 1 'C30-30' => 1 'C200' => HASH(0x1835318) 'C200-1' => 1 'C200-3' => 1 'C200-20' => 1 'C200-21' => 1

Comment on How to sort hash tables alpha-numeric
Download Code
Re: How to sort hash tables alpha-numeric
by Aragorn (Curate) on Oct 18, 2003 at 17:48 UTC
    Here's a solution using the so-called Schwartzian transform for sorting the keys (the leading "C" is stripped off, and the the key list is sorted by the number before the dash, and then by the number after the dash:
    #!/usr/bin/perl use warnings; use strict; my %keys; $keys{'C10'}->{'C10-1'}=1; $keys{'C10'}->{'C10-2'}=1; $keys{'C10'}->{'C10-20'}=1; $keys{'C10'}->{'C10-3'}=1; $keys{'C200'}->{'C200-1'}=1; $keys{'C200'}->{'C200-20'}=1; $keys{'C200'}->{'C200-3'}=1; $keys{'C200'}->{'C200-21'}=1; $keys{'C30'}->{'C30-1'}=1; $keys{'C30'}->{'C30-2'}=1; $keys{'C30'}->{'C30-30'}=1; $keys{'C30'}->{'C30-4'}=1; sub sorted { return map { $_->[0] } sort { $a->[1] <=> $b->[1] || $a->[2] <=> $b->[2] } map { [ $_, split("-", substr($_,1)) ] } @_; } foreach my $key (sorted(keys %keys)) { print "'$key' => ", $keys{$key}, "\n"; foreach my $subkey (sorted(keys %{$keys{$key}})) { print " '$subkey' => $keys{$key}->{$subkey}\n"; } }

    Arjen

      This works perfect although I don't understand yet 100% how the Schwartzian transform works. Their is one small problem that I have with the code is that it should look for all leading characters to be split because now it substr only one but it could be more. (CR30-1 for example) So I tried to modify the code but no success.
      sub sorted { return map { $_->[0] } sort { $a->[1] <=> $b->[1] || $a->[2] <=> $b->[2] } map { [ $_, split("-", s/^[A-Z]+//) ] } @_; } foreach my $key (sorted(keys %keys)) { print "'$key' => ", $keys{$key}, "\n"; foreach my $subkey (sorted(keys %{$keys{$key}})) { print " '$subkey' => $keys{$key}->{$subkey}\n"; } }
        The Schwartzian Transform is explained here by the person after who this sorting technique is named.

        A modified version of the sorted routine which also takes the leading letters into account:

        sub sorted { return map { $_->[0] } sort { $a->[1] cmp $b->[1] || $a->[2] <=> $b->[2] || $a->[3] <=> $b->[3] } map { [ $_, (/([A-Z]+)(\d+)(?:-(\d+)){1,2}/) ] } @_; }
        The split function is replaced by a regex which returns a list of letters and the numbers.

        Arjen

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others wandering the Monastery: (7)
As of 2014-12-29 02:56 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (184 votes), past polls