2015-05-22 2 views
1

Я пытаюсь присвоить массив значение в моей хэш следующим образом:Perl - Присвоить массив в другой переменной

$authors->[$x]->{'books'} = @books; 

$authors является массив хэшей, который содержит его/ее имя , фамилия, дата рождения и т. д. И теперь я создаю ключ books, где я хочу назначить массив книг. Однако, когда я пытаюсь напечатать его послесловие, это просто печать размера массива, как будто я делаю $value = scalar @books.

Что я делаю неправильно?

ответ

8

Элементы массива и хэш-значения являются скалярами, поэтому, когда вы вставляете массивы и хеши, вы должны использовать ссылки. Точно так же, как $authors->[$x] не хеш, а ссылка на хэш, вы должны установить $authors->[$x]->{'books'} в ссылку на массив.

$authors->[$x]->{'books'} = \@books; # reference the original array 
$authors->[$x]->{'books'} = [@books]; # reference a copy 

Вы бы затем получить доступ к элементам массива, используя что-то вроде

$authors->[$x]->{'books'}->[0] 

, который может быть сокращенным

$authors->[$x]{books}[0] 

или получить доступ весь массив, как

@{$authors->[$x]{books}} 

Ваш оригинальная попытка

$authors->[$x]->{'books'} = @books; 

в точности эквивалентен

$authors->[$x]->{'books'} = scalar @books; 

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

P.S.

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

+0

Спасибо! Это сработало. В чем разница между методом «ссылка на исходный массив» и методом «ссылка на копию»? И что подразумевается под «ссылкой»? Это то же самое, что и в C? – Ricky

+1

@Ricky '[@books]' (вы можете вызвать '[]' анонимный конструктор массива) принимает '@ books' и делает копию, которая может быть сохранена как ссылка« анонимно ». С '\ @ books' вы ссылаетесь на исходный массив. Это имеет значение, если вы меняете любой из элементов - * i.e *.изменяет ли копия или ссылку ** и ** оригинал? См. ['Perldoc perlreftut'] (http://perldoc.perl.org/perlreftut.html) и [' perldoc perlref'] (http://perldoc.perl.org/perlref.html). Существует много удобных ссылок на руководство/блог, в которых сравниваются [ссылки perl и указатели C] (http://www.teaser.fr/~amajorel/psgfcp/) :-) –

+0

@ Ricky Запустите [** 're.pl' **] (https://metacpan.org/pod/Devel::REPL) или отладчика и попробуйте: 'my @ test1 = qw/qwerty /; my $ test2 = \ @ test1; my $ test3 = [@ test1] '. Затем 'pop' элемент из каждого из этих массивов' $ test2' и '$ test3' ссылается на массив и видит, как это влияет на' @ test1'. –

2

В то время как первый awnser абсолютно прав, в качестве альтернативы, вы можете также Ф.О. это:

push @{$authors->[$x]->{'books'}}, @books; 

Тогда $authors->[$x]->{'books'} будет массив, который содержит копию всех элементов из @books. Это может быть более «надежным», а затем работать со ссылками, как указано .

+0

erm .... * еще * массив ссылка. Вы использовали старый синтаксис. – tjd

+0

Да, вы правы, это то же самое, что и '$ authors -> [$ x] -> {'books'} = [@books]; # ссылка копия. Мой плохой, должен был выглядеть лучше на другом абрисе. – lamchob

Смежные вопросы