http://qs1969.pair.com?node_id=399954

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

Brethren,

I have a reference to a 2-D array ($xy) of floats. I would like to sort the y values (in descending order), but ideally I would like the x values to follow the sorting of y. One implementation that I came up with uses a hash as shown below to make a new array of x values that follows the y sort, but I'm sure there's a more efficient way to do this. My 2-D array can be pretty large (10k - 100k data points), so I'm interested in speed. Thanks for your suggestions.

my @x = @{$xy->[0]}; my @y = @{$xy->[1]}; my $i = 0; my %xyhash; foreach ( @x ) { $xyhash{ $_ } = $y[$i]; $i++ } my @x_sorted_by_y = sort{ $xyhash{$b} <=> $xyhash{$a} } keys %xyhash; my @sorted_y = sort{ $b <=> $a } @y; print "value of x with largest y = $x_sorted_by_y[0]\n"; print "largest y = $sorted_y[0] \n";

Regards chinman

Replies are listed 'Best First'.
Re: sorting question
by Enlil (Parson) on Oct 17, 2004 at 20:04 UTC
    This assumes you will have the same amount of x's as y's or you'll get a whole lot of uninitialized warnings (granted there are ways around that):
    use strict; use warnings; my $xy = [ [5,4,2,3,1,12], [2,9,2,3,4,5] ]; my @xy; #push x's and corresponding y coor. in #a slight different AoA; for ( 0 .. $#{$xy->[0]} ){ push @xy, [ $xy->[0][$_], $xy->[1][$_] ]; } #sort it by y; @xy = sort { $a->[1] <=> $b->[1] } @xy; print "value of x with largest y = $xy[-1][0]\n"; print "largest y = $xy[-1][1]\n";
Re: sorting question
by johnnywang (Priest) on Oct 17, 2004 at 19:59 UTC
    use strict; my $xy = [[1,2,3,4,5],[4,2,5,0,2]]; my @sorted = sort{$b->[1]<=>$a->[1] ||$b->[0]<=>$a->[0]} map{[$xy->[0] +->[$_],$xy->[1]->[$_]]} (0..$#{$xy->[0]}); print "($_->[0],$_->[1])\n" foreach @sorted;
Re: sorting question
by dave_the_m (Monsignor) on Oct 17, 2004 at 19:50 UTC
    @sorted_xy = sort { $a->[0] <=> $b->[0] || $a->[1] <=> $b->[1] } @xy;
    or threreabouts

    update:

    I misinterpreted the structure of $xy; I thought it was a list of coordinate pairs. Use one of the other solutions instead!

    Dave.

Re: sorting question
by chinman (Monk) on Oct 17, 2004 at 20:44 UTC
    Thanks everyone for the suggestions! Your suggestions are about twice as fast as the way I was attempting to do it.

    Regards chinman

Re: sorting question
by TedPride (Priest) on Oct 17, 2004 at 23:14 UTC
    I could be wrong, but it looks like you are using coordinate pairs. The following sorts coordinate pairs with y in descending order and x in ascending (since you didn't specify x to be descending as well):
    use strict; use warnings; my ($x, $y, $ref); for (0..20) { # Randomize some data points for testing $x = int rand 100; $y = int rand 100; $ref->[$_] = [$x,$y]; } for (sort {$b->[1] <=> $a->[1] or $a->[0] <=> $b->[0]} @$ref) { print $_->[0] . ',' . $_->[1] . "\n"; }