Вам просто нужно добавить sort перед каждым из ваших grep s:
my @sorted =
(
sort( grep /\.txt\z/, @files ),
sort( grep ! /\.txt\z/, @files )
);
Хитрость в том, что вы разбиваете список на части, а затем сортируете каждый раздел независимо. В зависимости от того, что вы делаете, это может быть намного лучше, чем пытаться делать все в одной операции сортировки. И наоборот, это не всегда может быть лучше.
Существуют и другие способы сделать это, но они не так просты. :)
Вот быстрый тест на моем MacBook Air с ванильным Perl 5.10.1:
There are 600 files to sort
brian: 3 wallclock secs @ 369.75/s (n=1161)
control: 3 wallclock secs @ 1811.99/s (n=5744)
leon: 4 wallclock secs @ 146.98/s (n=463)
mobrule: 3 wallclock secs @ 101.57/s (n=324)
sort: 4 wallclock secs @ 559.62/s (n=1746)
Вот сценарий:
use Benchmark;
use vars qw(@files);
@files = qw(
buster.pdf
mimi.xls
roscoe.doc
buster.txt
mimi.txt
roscoe.txt
) x 100;
printf "There are %d files to sort\n", scalar @files;
sub leon {
my @sorted =
map { $_->[0] }
sort { $a->[1] <=> $b->[1] }
map { [ $_, !/\.txt$/ ]
} @files;
}
sub brian {
my @sorted =
(
sort( grep /\.txt\z/, @files ),
sort( grep ! /\.txt\z/, @files )
);
}
sub mobrule {
my @sorted =
sort { ($b=~/\.txt\z/) <=> ($a=~/\.txt\z/) || $a cmp $b }
@files;
}
sub plain_sort {
my @sorted = sort @files;
}
sub control {
my @sorted = @files;
}
timethese( -3,
{
brian => \&brian,
leon => \&leon,
mobrule => \&mobrule,
control => \&control,
sort => \&plain_sort,
}
);