Числовая сортировка массива

Проблема

Требуется отсортировать список чисел, однако функция 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;

См. также




2013-09-10 17:05:19

Proverte kod v komentariyah gde pro list tam oshibki detskie




Оставить комментарий:
Ваше Имя:
Email:
Антибот: *  
Ваш комментарий: