Как сортировать хеш perl по значениям и заказывать ключи соответственно (возможно, в двух массивах)?
В Perl я хочу сортировать ключи хэша по значению, численно:
{
five => 5
ten => 10
one => 1
four => 4
}
создает два массива:
(1,4,5,10) and (one, four, five, ten)
И затем я хочу нормализовать массив значений таким образом, чтобы числа были последовательными:
(1,2,3,4)
Как это сделать?
Ответы
Ответ 1
Сначала отсортируйте ключи по соответствующему значению. Затем получите значения (например, используя хэш-срез).
my @keys = sort { $h{$a} <=> $h{$b} } keys(%h);
my @vals = @h{@keys};
Или, если у вас есть хеш-ссылка.
my @keys = sort { $h->{$a} <=> $h->{$b} } keys(%$h);
my @vals = @{$h}{@keys};
Ответ 2
Как сортировать хэш (необязательно по значению вместо ключа)?
Чтобы отсортировать хэш, начните с ключей. В этом примере мы приводим список ключей функции сортировки, который затем сравнивает их ASCIIbetically (на которые могут влиять ваши настройки локали). Выходной список имеет ключи в ASCII-битезированном порядке. После того, как у нас есть ключи, мы можем пройти через них, чтобы создать отчет, в котором перечислены ключи в ASCII-формате.
my @keys = sort { $a cmp $b } keys %hash;
foreach my $key ( @keys ) {
printf "%-20s %6d\n", $key, $hash{$key};
}
Мы могли бы получить больше фантазии в блоке sort(). Вместо сравнения ключей мы можем вычислить значение с ними и использовать это значение в качестве сравнения.
Например, чтобы сделать наш порядок отчетов нечувствительным к регистру, мы используем lc для прокрутки ключей до их сравнения:
my @keys = sort { lc $a cmp lc $b } keys %hash;
Примечание. Если вычисление дорогостоящее или хеш имеет много элементов, вы можете посмотреть на преобразование Шварца, чтобы кэшировать результаты вычислений.
Если мы хотим сортировать по хэш-значению вместо этого, мы используем хеш-ключ для поиска. Мы по-прежнему получаем список ключей, но на этот раз они упорядочены по их значению.
my @keys = sort { $hash{$a} <=> $hash{$b} } keys %hash;
Оттуда мы можем усложниться. Если значения хэша одинаковы, мы можем предоставить вторичный сорт хэш-ключа.
my @keys = sort {
$hash{$a} <=> $hash{$b}
or
"\L$a" cmp "\L$b"
} keys %hash;
Ответ 3
См. раздел "Вопросы по Perl", озаглавленный "Как сортировать хеш (необязательно по значению вместо ключа)"
http://perldoc.perl.org/perlfaq4.html#How-do-I-sort-a-hash-%28optionally-by-value-instead-of-key%29?
Вы также можете использовать perldoc -q
для поиска часто задаваемых вопросов на вашем компьютере, например, в perldoc -q sort
, как я нашел ваш ответ.
Ответ 4
my ( @nums, @words );
do { push @nums, shift @$_;
push @words, shift @$_;
}
foreach sort { $a->[0] <=> $b->[0] }
map { [ $h->{ $_ }, $_ ] } keys %$h
;