В чем разница между хэшем и хеш-ссылкой в ​​Perl? - PullRequest
61 голосов
/ 30 ноября 2009

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

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

Очень хотелось бы получить хорошее объяснение хешей и ссылок на хеш, их различий, когда они необходимы и т. Д.

Ответы [ 4 ]

87 голосов
/ 30 ноября 2009

Простой хеш близок к массиву. Их инициализации даже похожи. Первый массив:

@last_name = (
  "Ward",   "Cleaver",
  "Fred",   "Flintstone",
  "Archie", "Bunker"
);

Теперь давайте представим ту же информацию с помощью хэша (он же ассоциативный массив):

%last_name = (
  "Ward",   "Cleaver",
  "Fred",   "Flintstone",
  "Archie", "Bunker"
);

Хотя они имеют одно и то же имя, массив @last_name и хэш %last_name полностью независимы.

С помощью массива, если мы хотим узнать фамилию Арчи, мы должны выполнить линейный поиск:

my $lname;
for (my $i = 0; $i < @last_name; $i += 2) {
  $lname = $last_name[$i+1] if $last_name[$i] eq "Archie";
}
print "Archie $lname\n";

С хэшем синтаксически он намного более прямой:

print "Archie $last_name{Archie}\n";

Скажем, мы хотим представить информацию с немного более богатой структурой:

  • Кливер (фамилия)
    • приход (имя)
    • июнь (имя супруга)
  • щебенки
    • Fred
    • Вильма
  • Бункер
    • Archie
    • Edith

До появления ссылок плоские хэши значений ключа были лучшими, что мы могли сделать, но ссылки позволяют

my %personal_info = (
    "Cleaver", {
        "FIRST",  "Ward",
        "SPOUSE", "June",
    },
    "Flintstone", {
        "FIRST",  "Fred",
        "SPOUSE", "Wilma",
    },
    "Bunker", {
        "FIRST",  "Archie",
        "SPOUSE", "Edith",
    },
);

Внутренне все ключи и значения %personal_info являются скалярами, но значения представляют собой особый вид скаляров: ссылки на хеш, созданные с помощью {}. Ссылки позволяют нам моделировать «многомерные» хеши. Например, мы можем добраться до Вилмы через

$personal_info{Flintstone}->{SPOUSE}

Обратите внимание, что Perl позволяет опускать стрелки между индексами, поэтому приведенное выше эквивалентно

$personal_info{Flintstone}{SPOUSE}

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

$fred = $personal_info{Flintstone};
print "Fred's wife is $fred->{SPOUSE}\n";

Поскольку $fred в приведенном выше фрагменте является хеш-кодом, стрелка необходима. Если вы оставите его, но умно включите use strict, чтобы помочь вам отлавливать подобные ошибки, компилятор будет жаловаться:

Global symbol "%fred" requires explicit package name at ...

Ссылки на Perl похожи на указатели в C и C ++, но они никогда не могут быть нулевыми. Указатели в C и C ++ требуют разыменования, как и ссылки в Perl.

Параметры функций C и C ++ имеют семантику передачи по значению: они просто копии, поэтому модификации не возвращаются к вызывающей стороне. Если вы хотите увидеть изменения, вы должны передать указатель. Вы можете получить этот эффект со ссылками в Perl:

sub add_barney {
    my($personal_info) = @_;

    $personal_info->{Rubble} = {
        FIRST  => "Barney",
        SPOUSE => "Betty",
    };
}

add_barney \%personal_info;

Без обратной косой черты add_barney получил бы копию, которая выбрасывается, как только саб возвращается.

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

16 голосов
/ 30 ноября 2009

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

my %hash = (
    toy    => 'aeroplane',
    colour => 'blue',
);
print "I have an ", $hash{toy}, " which is coloured ", $hash{colour}, "\n";

my $hashref = \%hash;
print "I have an ", $hashref->{toy}, " which is coloured ", $hashref->{colour}, "\n";

Также см. perldoc perldsc .

10 голосов
/ 30 ноября 2009

Хеш - это основной тип данных в Perl. Он использует ключи для доступа к своему содержимому.

Ссылка на хэш - это сокращение от ссылка на хеш. Рекомендации скаляры, то есть простые значения. это скалярное значение, которое содержит по сути, указатель на фактический сам хэш.

Ссылка: разница между хэшем и ссылкой на хэш в perl - Форумы Ubuntu

Разница также в синтаксисе для удаления. Как и C, Perl работает для хэшей так:

delete $hash{$key};

и для хеш-ссылок

delete $hash_ref->{$key};

Perl Hash Howto - отличный ресурс для понимания хешей и хеша с помощью хеш-ссылок

Здесь также есть еще одна ссылка , которая содержит больше информации о perl и ссылках .

7 голосов
/ 30 ноября 2009

См. perldoc perlreftut , который также доступен в командной строке вашего компьютера.

Ссылка - это скалярное значение, которое относится ко всему массиву или целому хешу (или ко всему остальному). Имена - это один из видов ссылок, с которым вы уже знакомы. Подумайте о президенте Соединенных Штатов: грязный, неудобный мешок с кровью и костями. Но чтобы говорить о нем или представлять его в компьютерной программе, все, что вам нужно, - это простая и удобная скалярная строка «Барак Обама».

Ссылки в Perl похожи на имена для массивов и хэшей. Это личные, внутренние имена Perl, так что вы можете быть уверены, что они однозначны. В отличие от «Барака Обамы», ссылка относится только к одной вещи, и вы всегда знаете, к чему она относится. Если у вас есть ссылка на массив, вы можете восстановить весь массив из него. Если у вас есть ссылка на хеш, вы можете восстановить весь хеш. Но ссылка все еще является простым, компактным скалярным значением.

...