Вы не говоря уже о том, как вы сравнить эти данные. Это делается по названию книги? Или это делается автором? Это затрудняет понимание того, как эта информация должна быть сохранена.
Ваши данные немного сложнее, чем хранение отдельных фрагментов данных. Это означает, что структуры данных Perl по умолчанию, скаляр ($foo
), массив (@foo
) и хэш (%foo
) просто не будут его обрезать. Пришло время узнать о references.
Технически ссылка - это место в памяти, где хранится какой-либо другой элемент. Вы создаете ссылку, поставив обратную косую черту перед именем:
$ref_to_foo_array = \@foo;
$ref_to_foo_array
это место в памяти, где мой @foo
массив хранится.Большим преимуществом является обращение к целому массиву значений, теперь я имею в виду одно значение: Место в памяти, где хранится @foo
. Это означает, что я могу поставить эту информацию в массив или хэш:
$bar[0] = $ref_to_foo_array;
$bar[1] = $ref_to_some_other_array;
Теперь @bar
не только хранить два значения. Вместо этого @bar
хранит информацию в двух массивах! У меня есть массив массивов !.
Чтобы получить обратно свой исходный массив, я просто разыменовать его, поставив правильный сигилу перед моим Справочно:
@foo = @{ $bar[0] };
Чтобы сделать вещи проще, я могу использовать ->
как средство разыменовании одно значение:
$array_reference = $bar[0];
$array_reference->[0]; # First item in the array being referenced
$array_reference->[1]; # Second item
конечно, я мог бы сделать это тоже:
$bar[0]->[0] # First item in the array being referenced
Так что же все это делать? Часы:
use strict;
use warnings;
use autodie;
use feature qw(say);
use constant {
BOOK_FILE => 'psychnet3.data',
};
open my $book_fh, "<", BOOK_FILE;
my %book_hash;
for my $book (<$book_fh>) {
chomp $book;
my ($title, $author, $section, $shelf) = split /\s*\|\s*/, $book;
my $temp_book_hash;
$temp_book_hash{AUTHOR} = $author;
$temp_book_hash{SECTION} = $section;
$temp_book_hash{SHELF} = $shelf;
$book_hash{$title} = \$temp_book_hash;
}
У меня есть %temp_book_hash
, заклиненный по названию книги. Тем не менее, этот единственный хэш хранит автора, раздел и «я», где хранится эта книга. Каждая книга имеет три разных бита информации, связанных с ней, но я могу хранить всю эту информацию в единой структуре данных. Нет необходимости хранить параллельные массивы или хеши.
Как получить эту информацию? Простой:
my $title = "To Kill a Mockingbird";
my %temp_book_hash = %{ $book_hash{$title} };
say "The book $title was written by $temp_book_hash{AUTHOR}";
По разыменования Хэш я хранится в $book_hash{$title}
, я могу вытащить имя автора, и подача информации.
Синтаксис немного неуклюжий. Я постоянно делаю временные переменные, чтобы передавать информацию туда и обратно. К счастью, Perl позволяет мне пропустить этот шаг. Вот тот же цикл, как и раньше:
for my $book (<$book_fh>) {
chomp $book;
my ($title, $author, $section, $shelf) = split /\s*\|\s*/, $book;
$book_hash{$title} = {}; # Line not necessary
$book_hash{$title}->{AUTHOR} = $author;
$book_hash{$title}->{SHELF} = $shelf;
$book_hash{$title}->{SECTION} = $section;
}
Вместо того, что временный хэш, я могу хранить дату непосредственно в мой самый внешний хэш. Этот синтаксис намного короче и чище. И это легче понять.
Линия $book_hash{$title} = {};
заявляет, что $book_hash{$title}
будет хранение хэша-ссылки, а не какая-то стандартная строки или номера. Эта строка не нужна вообще. Perl выяснит, что вы храните хеш-ссылку с $book_hash{$title}->{AUTHOR} = $author;
. Тем не менее, мне нравится _declare мое намерение, что я храню ссылку в этой переменной. Таким образом, если дальше в моей программе есть $book_hash{$title} = $author;
, другой разработчик узнает, что я допустил ошибку.
я могу использовать тот же ->
нотацию, чтобы вытащить информацию из моей книги, без необходимости создания временных переменных тоже:
my $title = "To Kill a Mockingbird";
say "The book $title was written by " . $book_hash{$title}->{AUTHOR};
Вы упомянули, что вы сравниваете два файла.Представьте себе, что я храню первый в %book_hash
, а второй - в $book_hash2
. Я могу пройти через мои книги и посмотреть, какие из них некорректно отложены.
for my $title (keys %book_hash) {
if ($book_hash{$title}->{SHELF} ne $book_hash2{$title}->{SHELF}) {
say "The book $title is stored on two different shelves!"
}
else {
say "The book $title is on the correct shelf";
}
}
Ссылки немного трудно понять, но я надеюсь, что вы можете увидеть силу быть в состоянии хранить всю информацию о вашей книге в одной структуре данных.
'my $ dbinfo =;' это будет читать только первую строку, поэтому будет дано только первый экземпляр. вам нужно сохранить в массиве, чтобы получить полный файл. 'my @dbinfo = ;' и может понадобиться другой цикл. Это всего лишь намек. Исходный код можно оптимизировать несколькими способами. –
jkshah
Пожалуйста, покажите содержимое 'psychnet3.data'. Это всего лишь одна строка? – Borodin
Что вы ожидаете от '@ dbarray'? – Borodin