Числовая сортировка массива
Проблема
Требуется отсортировать список чисел, однако функция Perl
sort (по умолчанию) выполняет
алфавитную сортировку в ASCII-порядке.
Решение
Воспользуйтесь функцией Perl sort с оператором числового сравнения, оператор <=>:
@Sorted = sort { $a <=> $b } @Unsorted;
Комментарий
При вызове функции sort можно передавать необязательный программный блок, с помощью которого
принятый по умолчанию алфавитный порядок сравнения заменяется вашим собственным. Функция сравнения
вызывается каждый раз, когда sort сравнивает две величины. Сравниваемые значения загружаются в
специальные пакетные переменные $а и $b, которые автоматически локализуются.
Функция сравнения должна возвращать отрицательное число, если значение $а должно находиться
в выходных данных перед $b; 0, если они совпадают или порядок несущественен; и положительное число,
если значение $а должно находиться после $b. В Perl существуют два оператора с таким поведением:
оператор <=> сортирует числа по возрастанию в числовом порядке, а cmp сортирует строки по возрастанию
в алфавитном порядке. По умолчанию sort использует сравнения в стиле cmp.
Следующий фрагмент сортирует список идентификаторов процессов (PID) в массиве @pids, предлагает
пользователю выбрать один PID и посылает сигнал TERM, за которым следует сигнал KILL. В необязательном
программном блоке $а сравнивается с $b оператором <=>, что обеспечивает числовую сортировку.
# @pids - несортированный массив идентификаторов процессов
foreach my $pid (sort { $a <=> $b } @pids) {
print "$pid\n";
}
print "Select a process ID to kill:\n";
chomp ($pid = <>);
die "Exiting ... \n" unless $pid && $pid =~ /^\d=$/;
kill ('TERM',$pid);
sleep 2;
kill ('KILL', $pid);
При использовании условия $a<=>$b или $а cmp $b список сортируется в порядке возрастания.
Чтобы сортировка выполнялась в порядке убывания, достаточно поменять местами $а и $b в функции сравнения:
@descending = sort { $b <=> $а } @unsorted;
Функции сравнения должны быть последовательными; иначе говоря, функция всегда должна возвращать
один и тот же ответ для одинаковых величин. Непоследовательные функции сравнения приводят к
зацикливанию программы или ее аварийному завершению, особенно в старых версиях Perl.
Также возможна конструкция вида sort ИМЯ СПИСОК, где ИМЯ — имя функции сравнения,
возвращающей -1, 0 или +1. В интересах быстродействия нормальные правила вызова не соблюдаются, а
сравниваемые значения, как по волшебству, появляются в глобальных пакетных переменных $а и $b.
Из-за особенностей вызова этой функции в Perl рекурсия в ней может не работать.
Предупреждение: значения $а и $b задаются в пакете, активном в момент вызова sort, — а он
может не совпадать с пакетом, в котором была откомпилирована передаваемая sort функция
сравнения (ИМЯ)! Например:
Package Sort_Subs;
sub revnum {$b <=> $a}
package Other_Pack;
@all = sort Sort_Subs::revnum 4, 19, 8, 3;
Такая попытка тихо заканчивается неудачей — впрочем, при наличии ключа -w о неудаче
будет заявлено вслух. Дело в том, что вызов sort создает пакетные переменные $а и $b в своем
собственном пакете, Other_Pack, а функция revnum будет использовать версии из своего пакета.
Это еще один аргумент в пользу встроенных функций сортировки:
@all = sort { $b <=> $а } 4, 19, 8, 3;
См. также
Proverte kod v komentariyah gde pro list tam oshibki detskie
Оставить комментарий:
|
|