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

I'm currently creating keys by joining a number of input .txt file fields:

my @F = split("\t", $_); $freq{join "\t", @F[0..1],@F[3..4]}++;

However the data is of mixed alphanumeric format, an example key would be:

1    12301    A    B

When it comes to printing and handling the hash contents, I want to be able to sort the keys numerically - by the first number and then by the second, so that it would print like this:

1 12301 A B 1 12310 A B 2 4501 A B 2 15410 A B

And so forth.

Is this at all possible with the way the keys are currently created? Would it simply be easier to use a multidimensional hash and then nested loops to try and handle accessing the elements?

Replies are listed 'Best First'.
Re: Sorting a mixed-format hash key
by hippo (Archbishop) on Aug 11, 2016 at 12:50 UTC
    Is this at all possible with the way the keys are currently created?

    Yes, of course. See the last example of How do I sort an array by (anything)? as a guide.

    Would it simply be easier to use a multidimensional hash and then nested loops to try and handle accessing the elements?

    Conceivably. However, I think the simplest approach is to extract a single sortable number from each key which you could do like this:

    my $index = sprintf("%i.%6.6i", split (/\t/, $key));

    Whether you use this number as the actual key or just use it to sort and then reassemble is up to you.

Re: Sorting a hash that has mixed-format keys
by planetscape (Chancellor) on Aug 11, 2016 at 13:37 UTC
Re: Sorting a hash that has mixed-format keys
by AnomalousMonk (Archbishop) on Aug 11, 2016 at 14:39 UTC

    Here's an example of what hippo was talking about. Note that it only works for positive integers in the range 0 .. 4,294,967,295.

    c:\@Work\Perl\monks>perl -wMstrict -le "use Data::Dump qw(dd); ;; my @raw_keys = ( '1 12301 A B', '2 4501 A B', '1 12299 E F', '2 4502 C D', '1 12310 A B', '2 4499 C D', '2 15410 A B', ); ;; my $ornament = 'N N'; my $decorate = qq{ $ornament a*}; my $undecorate = qq{x[$ornament] a*}; ;; my @sorted_keys = map unpack($undecorate), sort map pack($decorate, (split ' ', $_, 3)[0,1], $_), @raw_keys ; dd \@sorted_keys; " [ "1 12299 E F", "1 12301 A B", "1 12310 A B", "2 4499 C D", "2 4501 A B", "2 4502 C D", "2 15410 A B", ]


    Give a man a fish:  <%-{-{-{-<

Re: Sorting a hash that has mixed-format keys
by perldigious (Priest) on Aug 11, 2016 at 13:05 UTC

    You should be able to access the keys using keys and store them in an array, and then write a sort routine to priority sort by your first number then your second number extracted from each of those key using split and taking a slice of just the two numbers you want to sort by.

    I love it when things get difficult; after all, difficult pays the mortgage. - Dr. Keith Whites
    I hate it when things get difficult, so I'll just sell my house and rent cheap instead. - perldigious
Re: Sorting a hash that has mixed-format keys
by K_Edw (Beadle) on Aug 11, 2016 at 14:20 UTC
    Thanks guys! Lots of helpful information. I'll see what I can put together.