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

Hi,
I was wondering if anyone could help me with figuring out how to sort by value in descending order. Right now, I'm getting my inputs from different reports generated from different sources. I have the following foreach loop:
foreach $Name(sort keys %x) { $total_x= $x{$Name}; $total_y= $y($Name}; if ($total_y> 0) { $total_value= $total_x/$total_y; printf INTFILE "%-50s %10.3f %15.2f %10.3f %10.5f\n", $Name, $ +total_x, $total_y, $total_value; }
The output file looks like:
Name x y total_value abc 3 4 5 xyz 2 1 8
I want to sort the output such that everything is sorted in descending order based on the total_value, so the output should be:
Name x y total_value xyz 2 1 8 abc 3 4 5
The problem is that the computation of total_value is done inside the loop, so I was wondering if there was anyway around it. I need to keep the foreach loop to get the values of x and y. Thanks.

-r

Edit by dws to add <code> tags

Replies are listed 'Best First'.
Re: Sorting by Value
by Abigail-II (Bishop) on Jul 19, 2002 at 15:46 UTC
    That's strange. You calculate $total_value as $total_x/$total_y, then print out $total_x, $total_y, $total_value, and get 2, 1, 8 and 3, 4, 5. Your Perl must be really, really broken. Also, your format for printf has 5 %'s, but you only have 4 parameters.

    Anyway, the answer is the preprocess the data.

    map {printf INFILE "%-50s %10.3f %10.3f %10.5f\n" => @$_} sort { $a -> [3] <=> $b -> [3]} map {[$_, $x {$_}, $y {$_}, $x {$_} / $y {$_}]} grep { $y {$_} > 0} keys %x;

    Abigail

Re: Sorting by Value
by simeon2000 (Monk) on Jul 19, 2002 at 15:57 UTC
    As far as writing out the solution for you, I will not for I am having a hard time deciphering your post in the first place.

    However, sorting a hash in reverse by value as opposed to by key is as simple as:

    my %hash = ( 'A' => 5, 'B' => 4, 'C' => 3, 'D' => 2, 'E' => 1 ); for my $key (sort { $hash{$b} <=> $hash{a} } keys %hash) { #... }

    I believe will give you the desired effect. Try perldoc -q sort on the command line for more details.