Описание функции
Sort — это встроенная функция perl.
|
1 |
sort LIST |
По умолчанию, sort сравнивает элементы переданного списка как строки, сортирует их в алфавитном порядке и возвращает отсортированный список. Если задана директива use locale, при сортировке будут учитываться национальные установки.
|
1 2 |
sort USERSUB LIST sort BLOCK LIST |
Суть сортировки заключается в том, чтобы брать по два элемента из списка и сравнивать их между собой, определяя, какой из этих элементов будет стоять первым в итоговом списке.
Если необходимо изменить порядок сортировки, например, сортировать список из чисел, можно задать специальный блок сортировки.
Во время работы, sort присваивает значения из заданного списка двум специальным переменным $a и $b, и сравнивает их между собой. Эти переменные доступны в блоке сортировки.
Блок сортировки должен определить, какой из элементов должен быть «первым» в итоговом списке, и вернуть функции sort() значение:
- -1, если «первым» будет значение переменной $a,
- 1, если «первым» будет значение переменной $b,
- 0, если порядок следования не имеет значения.
Можно вместо блока сортировки написать отдельную функцию, которая будет выполнять те же
действия, и передать sort ссылку на нее.
$a и $b являются глобальными переменными, поэтому объявлять их дополнительно не нужно.
Примеры использования функции sort()
Операторы <=> и cmp
Операторы <=> и cmp сравнивают между собой две скалярные величины и возвращают число, означающее результат сравнения.
Алгоритм работы:
- если левый аргумент < правый аргумент функция вернет -1
- если левый аргумент > правый аргумент функция вернет 1
- если левый аргумент == правый аргумент функция вернет 0
Оператор <=> сравнивает между собой числа.
|
1 |
print(1 <=> 2); # вернет -1 |
Оператор cmp сравнивает строки по алфавиту. Строка, начинающаяся с буквы, которая идет в алфавите раньше другой, будет считаться «меньшей» оператором сравнения.
|
1 |
print("alisa" cmp "jane"); # вернет -1 |
Операторы сравнения возвращают данные именно в таком формате, в каком это требуется функции sort, и поэтому идеально подходят для использования при сортировке данных с ее помощью.
Сортировка с помощью операторов <=> и cmp
Простая сортировка числового ряда
|
1 2 3 |
my @array = qw(1 5 10 3 7); print join(' ', sort {$a<=>$b} @array ); # вывод: 1 3 5 7 10 |
Сортировка ключей хеша по значениям
|
1 2 3 4 5 6 7 |
my %hash = ( 1 => 'Nino', 10 => 'Jass', 5 => 'Glory', ); my @sorted_keys = sort {$hash{$a} cmp $hash{$b}} keys %hash ; |
Сортировка значений хеша
|
1 |
print join " ", sort {$a cmp $b} values %hash; |
Сортировка сложной структуры данных
Допустим, есть хеш с номерами телефонов сотрудников. Нужно отсортировать его по именам сотрудников.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
my %hash = ( 2345 => { name => 'Alexa', office => '342', }, 2458 => { name => 'Nino', office => '423', }, 3445 => { name => 'Glory', office => '2', }, ); foreach my $key (sort {$hash{$a}->{name} cmp $hash{$b}->{name}} keys %hash) { print $key." = ".$hash{$key}->{name}."\n"; } |
Вывод:
|
1 2 3 |
2345 = Alexa 3445 = Glory 2458 = Nino |
Сортировка сложной структуры данных по нескольким параметрам
Отсортируем список сотрудников по именам и номерам офиса.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
my %hash = ( 2345 => { name => 'Alexa', office => '342', }, 2458 => { name => 'Nino', office => '423', }, 2459 => { name => 'Jess', office => '423', }, 3445 => { name => 'Glory', office => '342', }, ); foreach my $key (sort sort_func keys %hash) { print $hash{$key}->{office}." = ".$hash{$key}->{name}."\n"; } sub sort_func { $hash{$a}->{name} cmp $hash{$b}->{name} || $hash{$a}->{office} <=> $hash{$b}->{office}; } |
Вывод:
|
1 2 3 4 |
342 = Alexa 342 = Glory 423 = Jess 423 = Nino |
Сортировка сложной структуры данных по нескольким параметрам 2
В данном примере у нас не хеш хешей, а массив хешей. Сортируем так же, по именам сотрудников и номеру офиса.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
my @array = ( { name => 'Alexa', office => '342', }, { name => 'Nino', office => '423', }, { name => 'Jess', office => '423', }, { name => 'Glory', office => '342', }, ); foreach (sort sort_func @array) { print $_->{office}." = ".$_->{name}."\n"; } sub sort_func { $a->{name} cmp $b->{name} || $a->{office} <=> $b->{office}; } |
Вывод:
|
1 2 3 4 |
342 = Alexa 342 = Glory 423 = Jess 423 = Nino |
Полезные ссылки
Функция sort
perldoc.perl.org: sort
www.perlfect.com: Sorting Techniques
Алгоритмы сортировки
perldoc.perl.org: Sort — perl pragma to control sort() behaviour
www.perltutorial.org: Perl Sorting Algorithms
преклоняюсь перед представительницами прекрасного пола изучающими программирование или стезю администрирования. Прекрасная статья.
Присоединяюсь, автору огромное спасибо!
а если числа сравнивать cmp то что?
Тогда сортировка будет по правилам «алфавита». Сначала будут выведены цифры, потом буквы. Числа будут сортироваться в порядке от 1 до 9, но не по своему числовому значению, а по длине и порядку следования в них цифр, как если бы сортировались слова:
сначала будут выводиться «май», потом «мария», потом «маска», потом «мир». Точно так же и цифры будут отсортированы: сначала «1», потом «11», потом «2».
Пример:
my @arr = (1, 2, 3, 5, 'c', 110, 34, 'a');print join(' ', sort {$a cmp $b} @arr );
Результат:
1 110 2 3 34 5 a c
Вы не могли бы подсказать, как можно провести суммирование значений хеша? Например, имеется такой хеш: my %р = (‘груши’=> 20.5, ‘яблоки’=> 17.8, ‘сливы’=> 30.35, ‘арбуз’=> 15.8, ‘груши’=> 10.0, ‘сливы’=> 20.0). Нужно просуммировать значения с одинаковыми ключами, чтобы в итоге получился такой результат:
груши 30,5
яблоки 17,8
сливы 50,35
арбуз 15,8
Я пока только начинаю разбираться с хешами, не все моменты по ним понятны, хотела бы попросить совет у практикующего perl-программиста :-)
Спасибо!