in reply to Sort then conditionally sort
There's no way to know whether to sort Y ascending or descending before X is fully sorted, so you'll need to do multiple passes.
use strict; use warnings; my @data; while (<DATA>) { chomp; push @data, [ split /\s+|,/ ]; } @data = sort { $a->[0] cmp $b->[0] || $a->[1] <=> $b->[1] } @data; my %order; my $last_f; my $last_x; for (@data) { if (!defined($last_f) || $last_f ne $_->[0]) { $order{$_->[0]}{$_->[1]} = +1; $last_f = $_->[0]; $last_x = $_->[1]; } if ($last_x ne $_->[1]) { $order{$_->[0]}{$_->[1]} = -$order{$last_f}{$last_x}; $last_x = $_->[1]; } } @data = sort { $a->[0] cmp $b->[0] || $a->[1] <=> $b->[1] || ( $a->[2] <=> $b->[2] ) * $order{$a->[0]}{$a->[1]} } @data; print("$_->[0] $_->[1],$_->[2]\n") for @data; __DATA__ ...
Update: By sorting only one dimension at a time, we can avoid multiple passes. It actually makes the program simpler:
use strict; use warnings; my %data; while (<DATA>) { chomp; my ($f,$x,$y) = split /\s+|,/; push @{ $data{$f}{$x} }, $y; } my @data; my $order = +1; for my $f (sort keys %data) { my $xs = $data{$f}; for my $x (sort { $a <=> $b } keys %$xs) { my $ys = $xs->{$x}; push @data, map [ $f, $x, $_ ], sort { $order * ( $a <=> $b ) } @$ys; $order *= -1; } } print("$_->[0] $_->[1],$_->[2]\n") for @data; __DATA__ ...
In both case, the data was
aaa 1,2 aaa 2,1 aaa 2,3 aaa 3,1 aaa 3,2 aaa 4,1 aaa 4,5 bbb 2,2 bbb 2,5 bbb 2,1 bbb 4,3 bbb 4,6 bbb 4,1 bbb 4,2 ccc 3,3 ccc 3,6 ccc 1,3 ccc 1,1 ccc 6,4 ccc 6,6 ccc 2,2 ccc 2,4
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^2: Sort then conditionally sort
by lukez (Initiate) on Apr 10, 2009 at 17:18 UTC | |
by ikegami (Patriarch) on Apr 11, 2009 at 06:44 UTC | |
|
Re^2: Sort then conditionally sort
by lukez (Initiate) on Apr 10, 2009 at 04:22 UTC | |
by ikegami (Patriarch) on Apr 11, 2009 at 06:52 UTC | |
by lukez (Initiate) on Apr 15, 2009 at 00:10 UTC | |
by ikegami (Patriarch) on Apr 15, 2009 at 02:31 UTC |