Что решает порядок ключей при печати Perl-хеша? - PullRequest
5 голосов
/ 06 января 2010

activePerl 5.8 на основе

#!C:\Perl\bin\perl.exe
use strict;
use warnings;

# declare a new hash
my %some_hash;

%some_hash = ("foo", 35, "bar", 12.4, 2.5, "hello",
      "wilma", 1.72e30, "betty", "bye\n");

my @any_array;
@any_array = %some_hash;

print %some_hash;
print "\n";
print @any_array;
print "\n";
print $any_array[0];
print "\n";
print $any_array[1];
print "\n";
print $any_array[2];
print "\n";
print $any_array[3];
print "\n";
print $any_array[4];
print "\n";
print $any_array[5];
print "\n";
print $any_array[6];
print "\n";
print $any_array[7];
print "\n";
print $any_array[8];
print "\n";
print $any_array[9];

Вывод как это

D:\learning\perl>test.pl
bettybye
bar12.4wilma1.72e+030foo352.5hello
bettybye
bar12.4wilma1.72e+030foo352.5hello
betty
bye

bar
12.4
wilma
1.72e+030
foo
35
2.5
hello
D:\learning\perl>

Что решило порядок печати элементов в моем примере кода?

Есть ли какое-либо правило, которое нужно соблюдать при печати смешанного хеша (строки, числа) в Perl? Спасибо.

bar12.4wilma1.72e+030foo352.5hello

[Обновлено]

С вашей помощью, ребята, я обновил код, как показано ниже.

#!C:\Perl\bin\perl.exe
use strict;
use warnings;

# declare a new hash
my %some_hash;

%some_hash = ("foo", 35, "bar", 12.4, 2.5, "hello",
      "wilma", 1.72e30, "betty", "bye");

my @any_array;
@any_array = %some_hash;

print %some_hash;
print "\n";
print "\n";
print @any_array;
print "\n";
print "\n";

my @keys;
@keys = keys %some_hash;
for my $k (sort @keys)
{
    print $k, $some_hash{$k};
}

выход

D:\learning\perl>test.pl
bettybyebar12.4wilma1.72e+030foo352.5hello

bettybyebar12.4wilma1.72e+030foo352.5hello

2.5hellobar12.4bettybyefoo35wilma1.72e+030
D:\learning\perl>

Наконец, после вызова keys и sort функций. Печать ключей хеша следовала правилу ниже

2.5hellobar12.4bettybyefoo35wilma1.72e+030

Ответы [ 8 ]

22 голосов
/ 06 января 2010

Элементы хеша распечатываются в их внутреннем порядке, на который нельзя положиться, и он будет изменяться при добавлении и удалении элементов. Если вам нужны все элементы хэша в некотором порядке, сортируйте ключи и используйте этот список для индексации хэша.

Если вы ищете структуру, которая содержит свои элементы по порядку, либо используйте массив, либо используйте один из упорядоченных хэшей в CPAN.

единственный порядок, на который вы можете положиться из расширения хэша контекста списка, состоит в том, что пары ключ => значения будут вместе.

9 голосов
/ 19 августа 2010

От ключей perldoc -f :

Ключи хэша возвращаются в явно случайном порядке. Фактический случайный порядок может быть изменен в будущих версиях Perl, но он гарантированно будет того же порядка, что и значения, которые выдает каждая функция (учитывая, что хэш не был изменен). Начиная с Perl 5.8.1, порядок разный даже для разных запусков Perl по соображениям безопасности (см. Атаки алгоритмической сложности в perlsec ).

...

Perl никогда не гарантировал какого-либо упорядочивания ключей хеша, и упорядочение уже несколько раз менялось за время существования Perl 5. Кроме того, порядок упорядочения ключей хеша всегда был и остается под влиянием порядка вставки .

Также обратите внимание, что хотя порядок элементов хеш-функции может быть случайным, этот «псевдопорядок» не должен использоваться для приложений, таких как случайное перемешивание списка (для этого используйте List :: Util :: shuffle (), см. List :: Util , стандартный базовый модуль начиная с Perl 5.8.0 или модуль CPAN Algorithm :: Numeric :: Shuffle ), или для генерации перестановок (используйте, например, модули CPAN Algorithm :: Permute или Algorithm :: FastPermute ), или для любых криптографических приложений.


Примечание: поскольку вы оцениваете хеш в контексте списка, вы гарантируете , что за каждым ключом следует соответствующее значение; например вы никогда не увидите вывод a 4 b 3 c 2 d 1.

3 голосов
/ 06 января 2010

Я просмотрел ваш код и сделал несколько заметок, которые, я думаю, вы найдете полезными.

use strict;
use warnings;

# declare a new hash and initialize it at the same time
my %some_hash = (
    foo   => 35,       # use the fat-comma or '=>' operator, it quotes the left side
    bar   => 12.4,     
    2.5   => "hello",
    wilma => 1.72e30,
    betty => "bye",    # perl ignores trailing commas, 
                       # the final comma makes adding items to the end of the list less bug prone.
);

my @any_array = %some_hash; # Hash is expanded into a list of key/value pairs.

print "$_ => $some_hash{$_}\n" 
    for keys %some_hash;

print "\n\n",              # You can print multiple newlines in one string.
      "@any_array\n\n";    # print takes a list of things to print.

# In print @foo; @foo is expanded into a list of items to print.  
# There is no separator between the members of @foo in the output.

# However print "@foo"; interpolates @foo into a string. 
# It inserts spaces between the members of the arrays.


# This is the block form of 'for'
for my $k (sort keys %some_hash)
{
    # Interpolating the variables into a string makes it easier to read the output.
    print "$k => $some_hash{$k}\n";
}

Хеши обеспечивают неупорядоченный доступ к данным с помощью строкового ключа.

Массивы обеспечивают доступ к заказанным данным. Произвольный доступ возможен при использовании числового индекса.

Если вам нужно сохранить порядок группы значений, используйте массив. Если вам нужно искать членов группы по связанному имени, используйте хеш.

Если вам нужно сделать и то, и другое, вы можете использовать обе структуры вместе:

# Keep an array of sorted hash keys.
my @sorted_items = qw( first second third fourth );

# Store the actual data in the hash.
my %item;
@item{ @sorted_items } = 1..4;  # This is called a hash slice.  
                                # It allows you to access a list of hash elements.
                                # This can be a very powerful way to work with hashes.

# random access
print "third => $item{third}\n";


# When you need to access the data in order, iterate over
# the array of sorted hash keys.  Use the keys to access the
# data in the hash.

# ordered access
for my $name ( @sorted_items ) {
    print "$name => $item{$name}\n";
}

Глядя на ваши примеры кода, я вижу пару вещей, над которыми вы можете поработать.

  • как циклические структуры, такие как for и while, могут использоваться для сокращения повторяющегося кода.
  • как использовать интерполяцию переменных

Кстати, я рад, что вы работаете над основами и улучшаете качество своего кода. Это вложение времени окупится. Продолжайте в том же духе.

2 голосов
/ 19 августа 2010

Хеши не (обязательно) извлекаются отсортированным образом. Если вы хотите, чтобы они были отсортированы, вы должны сделать это сами:

use strict;
use warnings;

my %hash = ("a" => 1, "b" => 2, "c" => 3, "d" => 4);

for my $i (sort keys %hash) {
    print "$i -> $hash{$i}\n";
}

Вы извлекаете все ключи из хэша, используя keys, а затем сортируете их, используя sort. Да, я знаю, этого сумасшедшего парня Ларри Уолла, который бы даже подумал назвать их , что? Это выводит:

a -> 1
b -> 2
c -> 3
d -> 4
2 голосов
/ 06 января 2010

Элементы (почти наверняка) распечатываются в порядке их появления (внутри) в самой хеш-таблице, т. Е. На основе значений хеш-кодов их ключей.

Общее правило, которое следует соблюдать, - это использовать что-то кроме хеш-таблицы, если вы очень заботитесь о порядке.

1 голос
/ 06 января 2010

Для большинства практических целей порядок, в котором хеш-таблица (не только хеш-переменные Perl, но и хеш-таблицы в целом) может считаться случайной.

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

Короткая версия, затем:

Не используйте хеш, если вы заботитесь о заказе (или об отсутствии заказа). Если вам нужен фиксированный порядок, он будет фактически случайным, а если вам нужен случайный порядок, он будет эффективно фиксированным.

0 голосов
/ 19 августа 2010

И если вы сумасшедший и у вас нет повторяющихся значений в вашем хэше, и вам нужны отсортированные значения, вы можете вызвать обратный вызов.

my %hash = ("a" => 1, "b" => 2, "c" => 3, "d" => 4);
my %reverse_hash = reverse %hash;

print $_ for sort keys %reverse_hash;

Caveat - это часть уникальных значений, дубликаты будут перезаписаны, и будет введено только одно значение.

0 голосов
/ 19 августа 2010

Хэш не определяет свойства упорядочения. Порядок выхода вещей будет непредсказуемым.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...