Сортировка хеша по значениям

Вскоре вы освоите сортировку списков и окажетесь в ситуации, когда хеш требуется отсортировать по значению. Допустим, трое уже знакомых персонажей отправились в боулинг, а их результаты хранятся в следующем хеше. Требуется вывести элементы списка в правильном порядке, начиная с победителя, так чтобы хеш был отсортирован по набранным очкам:

my %score = ("barney" => 195, "fred" => 205, "dino" => 30);
my @winners = sort by_score keys %score;

Конечно, мы вовсе не собираемся сортировать хеш по значениям; это всего лишь фигура речи. Хеш вообще нельзя отсортировать! Но в предыдущих примерах использования sort с хешами фактически выполнялась сортировка ключей хеша (в ASCII-алфавитном порядке). Сейчас мы опять собираемся отсортировать ключи хеша, но порядок сортировки определяется соответствующими значениями. Результат должен выглядеть как список имен, упорядоченных по набранным очкам. Написать функцию сортировки несложно. Все, что для этого нужно, – использовать числовое сравнение значений вместо строкового сравнения имен. Иначе говоря, вместо $a и $b (имена игроков) следует сравнивать $score{$a} и $score{$b} (набранные очки). Если взглянуть на задачу с этой точки зрения, программа пишется сама собой:

sub by_score { $score{$b} <=> $score{$a} }

Давайте разберемся, как она работает.


Допустим, при первом вызове $a содержит barney, а $b – fred. Значит, функция выполняет сравнение $score{"fred"} <=> $score{"barney"}, то есть (как видно из хеша) 205 <=> 195. Вспомните о «близорукости» оператора <=>: увидев 205 перед 195, он фактически говорит: «Нет, это неправильный числовой порядок; значение $b должно идти перед $a». В результате он сообщает Perl, что строка fred должна предшествовать barney. При следующем вызове функции $a снова содержит barney, а $b – dino. На этот раз числовое сравнение видит выражение 30 <=> 195 и сообщает, что элементы следуют в правильном порядке; $a действительно предшествует $b (то есть barney предшествует dino). На этой стадии Perl располагает достаточной информацией для упорядочения списка: fred – победитель, на втором месте barney и на третьем – dino. Почему в сравнении $score{$b} предшествует $score{$a}, а не наоборот? Потому что мы хотим упорядочить результаты игры по убыванию, от максимума к минимуму. Вскоре (опять же после небольшой тренировки) вы тоже научитесь читать такие конструкции «с листа»: $score{$b} <=> $score{$a} означает, что сортировка будет выполняться по набранным очкам, в числовом порядке и по убыванию.

Оцените статью: (0 голосов)
0 5 0

Статьи из раздела Perl на эту тему:
Использование функции sprintf для вывода денежных сумм
Операции с подстроками и функция substr
Поиск подстроки по индексу
Расширенная сортировка
Сортировка по нескольким ключам

Вернуться в раздел: Perl / 13. Строки и сортировка