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

Sort isn't acting like I expect it to and I'm a little confused. I have a hash reference that looks like this:
$sort_line_contents->{element_one}->{element_two}

I want to reverse sort on element_one (numerically) and then sort normally on element_two. Here is an example of my data set:

$sort_line_contents->{1}->{2} = Item1; $sort_line_contents->{0}->{3} = Item2; $sort_line_contents->{1}->{4} = Item3; $sort_line_contents->{1}->{5} = Item4; $sort_line_contents->{2}->{6} = Item5;

I want to take that information and force it into an order like this:
Item5
Item1
Item3
Item4
Item2

My first crack at this was using a sort statement like so:

my @hash_keys2 = sort { %{$sort_line_contents}->{$b} <=> %{$sort_li +ne_contents}->{$a} } keys %{$sort_line_contents};

But this gives me an incorrect order. Instead of giving me an order like this: 2, 1, 1, 1, 0 it gives me something like 0, 2, 1, 1, 1. I could not get this straightened out, so eventually ended up substituting this line:
foreach (reverse sort keys %{$sort_line_contents}) { push(@hash_keys2, +$_);}
I'm even more confused because the second sort using the second value works AS EXPECTED:
foreach my $hk (@hash_keys2){ my @filli = sort { $sort_line_contents->{$hk}->{$a} <=> $sort_li +ne_contents->{$hk}->{$b} } keys %{$sort_line_contents->{$hk}}; foreach (@filli){ #output to other part of program } }
My question is, why doesn't the sort on the hash ref give me the expected behaviour? Is there a problem with the way I am expanding my $sort_line_contents reference? I see that it is reading out the correct VALUES, it is just putting them in an unexpected order. I get the same unexpected order with the <=> and the cmp operators???

oakbox

Replies are listed 'Best First'.
Re: Sort not acting as expected on Hash Ref
by gjb (Vicar) on Jan 01, 2003 at 11:37 UTC

    Try this:

    foreach my $key (sort {$b <=> $a} keys %$sort_line_contents) { print join("\n", values %{$sort_line_contents->{$key}}), "\n"; }
    First the keys are sorted, and for each of those, all values are printed.

    Hope this helps, -gjb-

Re: Sort not acting as expected on Hash Ref
by jdporter (Paladin) on Jan 02, 2003 at 04:53 UTC
    What you have is really a reference/dereferencing problem, more than a sort problem. The sorts are simple enough, it's the ref stuff that's tricky.

    I believe this will do what you want:
    for my $e1 ( sort { $b <=> $a } keys %$sort_line_contents ) { for my $e2 ( sort keys %{ $sort_line_contents->{$e1} } ) { print $sort_line_contents->{$e1}->{$e2}, "\n"; } }

    jdporter
    The 6th Rule of Perl Club is -- There is no Rule #6.

Re: Sort not acting as expected on Hash Ref
by PodMaster (Abbot) on Jan 01, 2003 at 11:29 UTC
    Do you know what scalar %{$foo->{1}} gets you if $foo = { 1 => { 6,7 } , 2 => { 66,77 } };?

    I believe you simply want compare

    $foo->{$b} <=> $foo->{$a}


    MJD says you can't just make shit up and expect the computer to know what you mean, retardo!
    ** The Third rule of perl club is a statement of fact: pod is sexy.

      In a scalar context, hash would be evaluated to a fraction, which represents "number of buckets used" out of "number of buckets allocated". So it would be some kind of order related to memory usage.

      However what we got is a string representation of a fraction, so the order is not quite right, for example 13/16 would be less than 2/16.