Сторнирование хэша, получение его ключей и сортировка - PullRequest
3 голосов
/ 18 августа 2011

Я все еще изучаю Perl, так что, возможно, есть более эффективный способ сделать это.Я пытаюсь взять хеш, перевернуть его так, чтобы $ values ​​=> $ keys, захватить новый ключ (старое значение) и затем отсортировать эти ключи.

Вот код, о котором идет речь:

foreach my $key (sort keys reverse %hash){

...}

Что я ожидаю, так это то, что обратный% хеш вернет тип хеша, который и ищут ключи.Тем не менее, я получаю следующую ошибку:

Тип аргумента 1 для ключей должен быть хеш (не обратный)

Я пытался поместить скобки вокруг обратного% хеш, но все равно получаю то же.

Есть идеи, почему это не сработает?

Ответы [ 4 ]

6 голосов
/ 18 августа 2011

Функции Perl могут возвращать скалярные значения или списки; нет явного типа возвращаемого хеша (Вы можете вызвать return %hash из подпрограммы, но Perl неявно разворачивает пары ключ-значение из хеша и возвращает их в виде списка).

Следовательно, возвращаемое значение reverse %hash представляет собой список, а не хеш, и не подходит для использования в качестве аргумента keys. Вы можете заставить Perl интерпретировать этот список как хеш с помощью %{{}} cast:

foreach my $key (sort keys %{{reverse %hash}}) { ... 

Вы также можете отсортировать значения хеша, сказав

foreach my $key (sort values %hash) { ...

Использование values %hash несколько отличается от использования keys %{{reverse %hash}} тем, что keys %{{reverse %hash}} не будет возвращать повторяющихся значений.

4 голосов
/ 18 августа 2011

Аргументом keys должен быть хеш, массив или выражение, а не список.Если бы вы сделали

keys { reverse %hash }

, вы бы получили ожидаемый результат, потому что квадратные скобки создают анонимный хеш.Паренс, с другой стороны, только меняет приоритет.Или, в этом случае они, вероятно, считаются связанными с функцией keys(), так как большинство функций perl имеют необязательные символы скобок.

Также, если вы просто хотите получить значения хеша, вы можете использовать:

values %hash

См. Документацию для reverse , значения и ключи для получения дополнительной информации.

3 голосов
/ 18 августа 2011

Pre 5.14, keys возвращает ключи хэша.Это требует хеша.Вы не предоставили один.reverse не возвращает хэш.Фактически, невозможно вернуть хеш, так как могут быть возвращены только скаляры.(Внутренне, Perl может помещать хэши непосредственно в стек, но это никогда не будет видимо пользователю без появления сообщения об ошибке «Bizarre».) Эта ошибка обнаруживается во время компиляции.

5.14 более гибок,Он также примет ссылку на хеш.(Он также будет принимать массивы и ссылки на массивы, но здесь это не актуально.) Ссылки являются скалярами, поэтому они могут быть возвращены функциями.Ваш код фактически сделает его во время выполнения, но что бы вы ни возвращали reverse в скалярном контексте, это не будет ссылкой на несуществующий хеш, поэтому ваш код умрет в этот момент.


У вас есть причина хотеть изменить хеш?

foreach my $key (sort { $hash{$a} cmp $hash{$b} } keys %hash) {
   my $val = $hash{$key};
   ...
} 

Если вы это сделаете,

foreach my $val (sort keys %{ { reverse %hash } }) {
   # No access to original key
   ...
} 

или

my %flipped = reverse %hash;
foreach my $val (sort keys %flipped) {
   my $key = $flipped{$val};
   ...
} 
3 голосов
/ 18 августа 2011

Я думаю, что вы точно описываете ситуацию в этом примере :

#!/usr/local/bin/perl

use strict;
use warnings;

my %hash = (one   => 1, two  => 2, three => 3, four => 4);

%hash = reverse %hash;

foreach my $key (sort {$a <=> $b} keys %hash) {
    print "$key=>$hash{$key}, ";
}
print "\n";

# it displays: 1=>one, 2=>two, 3=>three, 4=>four 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...