В чем разница между хэшем и хеш-ссылкой в Perl?

50

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

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

Хорошее объяснение хешей и хеш-ссылок, их различия, когда они потребуются и т.д., будут очень оценены.

  • 37
    * протягивает тебе яблоко * притворяйся, что это хэш. * вручает вам инструкции к яблоку в холодильнике * это ссылка на хеш.
  • 2
    Вы можете проверить главу Изучения Perl о хешах.
Показать ещё 2 комментария
Теги:
hash
language-features

4 ответа

76
Лучший ответ

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

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

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

%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";

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

  • Кливер (фамилия)
    • Уорд (имя)
    • Июнь (имя супруга)
  • щебенки
    • Фред
    • Вильма
  • Бункер
    • 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, поэтому вы можете получить ссылку как своего рода курсор:

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

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

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

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

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

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

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

add_barney \%personal_info;

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

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

  • 0
    Бросим на 7 лет позже, чтобы заметить, что C и C ++ допускают передачу по ссылке без использования указателя. void f(DataType & arg) передает arg по ссылке и не требует разыменования для доступа или изменения.
  • 0
    @JimV Это когда вы передаете ссылку , объявленную с & , которая является своего рода псевдонимом. Семантика является передача по значению.
Показать ещё 1 комментарий
15

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

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.

  • 8
    Лично мне показалось странным видеть термин %hash для описания хеша. Это может быть хорошей идеей, чтобы переименовать ваш %hash как %favorite просто чтобы показать точку зрения. Тогда оператор print будет что-то вроде print "My favorite toy is the $favorite{toy}";
10

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

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

Ссылка: разница между hash и hash ref в perl - Форумы Ubuntu

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

delete $hash{$key};

и для ссылок Hash

delete $hash_ref->{$key};

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

Здесь есть еще одна ссылка которая содержит дополнительную информацию о perl и ссылках.

6

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

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

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

  • 0
    @ mjp66 Важной частью ответа является использование perldoc perlreftut который установлен вместе с perl на компьютере ОП. Это всегда самый точный документ для конкретной версии Perl, которую использует OP. Ссылка включена только в качестве любезности. Таким образом, в этом смысле URL-адреса документации по Perl похожи на ссылки. Содержимое ссылки может измениться, но ссылка всегда будет указывать на «Руководство по ссылкам Perl». Не все ссылки созданы равными. FYI.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню