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
In reply to Re: Sort then conditionally sort
by ikegami
in thread Sort then conditionally sort
by lukez
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |