Добавление нескольких значений для ввода хеша perl
Мне нужно создать многомерный хэш.
например я сделал:
$hash{gene} = $mrna;
if (exists ($exon)){
$hash{gene}{$mrna} = $exon;
}
if (exists ($cds)){
$hash{gene}{$mrna} = $cds;
}
где $gene
, $mrna
, $exon
, $cds
уникальные идентификаторы.
Но моя проблема в том, что я хочу, чтобы некоторые свойства $gene и $mrna были включены в хеш. например:
$hash{$gene}{'start_loc'} = $start;
$hash{gene}{mrna}{'start_loc'} = $start;
и т. д. Но возможно ли это для объявления хеша? Если я позвоню $hash{$gene}
и то и другое $mrna
а также start_loc
будет напечатан. Какое может быть решение?
Как бы я добавил несколько значений для одного и того же ключа $ gen и $mrna, являющихся ключами в этом случае.
Любые предложения будут оценены.
2 ответа
Что вам нужно сделать, это прочитать справочное руководство по Perl.
Простой ответ на ваш вопрос:
Хеши Perl могут принимать только одно значение ключа. Однако это единственное значение может быть ссылкой на ячейку памяти другого хэша.
my %hash1 = ( foo => "bar", fu => "bur" }; #First hash
my %hash2;
my $hash{some_key} = \%hash1; #Reference to %hash1
И ничто не мешает тому первому хешу содержать ссылку на другой хеш. Это черепахи вниз!,
Так что да, вы можете иметь сложную и запутанную структуру с любым количеством дополнительных хешей, сколько захотите. Или смешайте в некоторых массивах тоже.
По разным причинам я предпочитаю ->
синтаксис при использовании этих сложных структур. Я считаю, что для более сложных структур это облегчает чтение. Тем не менее, главное, это заставляет вас помнить, что это ссылки, а не реальные многомерные структуры.
Например:
$hash{gene}->{mrna}->{start_loc} = $start; #Quote not needed in string if key name qualifies as a valid variable name.
Лучше всего думать о вашем хэше как о структуре. Например:
my $person_ref = {}; #Person is a hash reference.
my $person->{NAME}->{FIRST} = "Bob";
my $person->{NAME}->{LAST} = "Rogers";
my $person->{PHONE}->{WORK}->[0] = "555-1234"; An Array Ref. Might have > 1
my $person->{PHONE}->{WORK}->[1] = "555-4444";
my $person->{PHONE}->{CELL}->[0] = "555-4321";
...
my @people;
push @people, $person_ref;
Теперь я могу загрузить массив @people всеми своими людьми или использовать хеш:
my %person;
$person{$bobs_ssn} = $person; #Now, all of Bob's info is index by his SSN.
Итак, первое, что вам нужно сделать, это подумать о том, как должна выглядеть ваша структура. Какие поля в вашей структуре? Какие подполя? Выясните, как должна выглядеть ваша структура, а затем настройте свой хэш хэшей таким образом. Выясните, как именно он будет храниться и записываться.
Помните, что этот хеш содержит ссылки на ваши гены (или что-то в этом роде), поэтому вы хотите правильно выбирать ключи.
Прочитайте учебник. Тогда попробуй свои силы в этом. Это не так сложно понять. Тем не менее, это может быть медведь для поддержания.
Когда ты сказал use strict;
Вы защищаете себя:
my $foo = "bar";
say $Foo; #This won't work!
Это не сработает, потому что вы не объявили $Foo
Вы заявили $foo
, use stict;
может поймать имена переменных, которые были опечатаны, но:
my %var;
$var{foo} = "bar";
say $var{Foo}; #Whoops!
Это не будет пойман (за исключением, может быть, что $var{Foo}
не был инициализирован. use strict;
Прагма не может обнаружить ошибки в наборе ключей.
Следующий шаг после того, как вы освоитесь со ссылками, - это перейти на объектно-ориентированный Perl. Для этого тоже есть учебник.
Все, что объектно-ориентированный Perl делает, это берет ваши хеш-ссылки и превращает их в объекты. Затем он создает подпрограммы, которые помогут вам отслеживать манипуляции с объектами. Например:
sub last_name {
my $person = shift; #Don't worry about this for now..
my $last_name = shift;
if ( exists $last_name ) {
my $person->{NAME}->{LAST} = $last_name;
}
return $person->{NAME}->{LAST};
}
Когда я задаю свою фамилию с помощью этой подпрограммы... Я имею в виду метод, я гарантирую, что ключ будет $person->{NAME}->{LAST}
и не $person->{LAST}->{NAME}
или же $person->{LAST}->{NMAE}
, или же $person->{last}->{name}
,
Основная проблема не в изучении механизмов, а в обучении их применению. Итак, подумайте, как именно вы хотите представлять свои предметы. Это о том, какие поля вы хотите, и как вы собираете эту информацию.
Вы можете попробовать поместить каждое значение в хэш массивов:
my (@gene, @mrna, @exon, @cds);
my %hash;
push @{ $hash{$gene[$_]} }, [$mrna[$_], $exon[$_], $cds[$_] ] for 0 .. $#gene;
Сюда gene
ключ с несколькими значениями ($mrna
, $exon
, $cds
) связано с этим.
Переберите ключи / значения следующим образом:
for my $key (sort keys %hash) {
print "Gene: $key\t";
for my $value (@{ $hash{$key} } ) {
my ($mrna, $exon, $cds) = @$value; # De-references the array
print "Values: [$mrna], [$exon], [$cds]\n";
}
}
Может быть полезен ответ на вопрос, который я задавал ранее ( может ли хеш-ключ иметь несколько "подзначений" в perl?).