Beefy Boxes and Bandwidth Generously Provided by pair Networks Joe
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 01:27 UTC ( [id://300236]=perlquestion: print w/replies, xml ) Need Help??

This is an archived low-energy page for bots and other anonmyous visitors. Please sign up if you are a human and want to interact.

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

Replies are listed 'Best First'.
Re: How to sort hash tables alpha-numeric
by Aragorn (Curate) on Oct 18, 2003 at 13: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
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://300236]
Approved by davido
help
Sections?
Information?
Find Nodes?
Leftovers?
    Notices?
    hippoepoptai's answer Re: how do I set a cookie and redirect was blessed by hippo!
    erzuuliAnonymous Monks are no longer allowed to use Super Search, due to an excessive use of this resource by robots.