2009-11-30 5 views
50

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

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

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

+35

_ * вручает вам яблоко * _ притвориться, что это хэш. _ * руки вы написали направления к яблоку в холодильнике * _ это хеш-ссылка. –

+2

Вы можете ознакомиться с главой Perl_ о хэшах. –

+0

@ ~ quack: Я бы хотел, чтобы это был ответ, а не комментарий, чтобы я мог правильно подправить вас. –

ответ

78

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

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

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

  • Кливер (фамилия)
    • Ward (первое название)
    • июня (первое имя супруга)
  • щебенки
    • Фред
    • Вильма
  • Бункер
    • 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 в приведенном выше фрагменте кода является hashref, стрелка необходимо.Если оставить его, но мудро позволил use strict, чтобы помочь вам поймать такого рода ошибок, компилятор будет жаловаться:

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

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

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

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

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

add_barney \%personal_info; 

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

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

+0

. Снижение на 7 лет спустя, чтобы отметить, что C и C++ позволяют передавать по ссылке без использования указателя. 'void f (DataType & arg)' передает 'arg' по ссылке и не требует разыменования для доступа или изменения. –

+0

@JimV Это когда вы передаете _reference_, объявленный с помощью '&', который является «своего рода» псевдонимом. Семантика _is_ pass-by-value. – zdim

+0

Отличная почта :). Комментарий - возможно, предупредительная записка была бы достойна того, что аргументы '@ _' сглаживают, поэтому один _can_ меняет их из суб (кроме хэш-ключей)? – zdim

10

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

A hash ref является аббревиатурой от ссылкой на хэш. Ссылки - это скаляры, то есть простые значения. Это скалярное значение, которое содержит , по существу, указатель на собственно гаджет .

Ссылка: difference between hash and hash ref in perl - Ubuntu Forums

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

delete $hash{$key}; 

и Hash Ссылки

delete $hash_ref->{$key}; 

Perl Hash Howto является большим ресурсом для понимания хэшей в сравнении Hash с Hash Ссылки

Существует также другой ссылка here that has more information on perl and references.

6

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

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

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

+0

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

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' как'% фаворита', чтобы просто проехать домой. Операция print была бы чем-то вроде «print». Моя любимая игрушка - это «любимая игрушка»; ' – Zaid