Добавление хеша к массиву
У меня есть такой массив,
@switch_ports = ()
а затем хотите добавить 50 экземпляров этого хэша в массив switch_ports
%port = (data1 => 0, data2 => 0, changed => 0)
однако, если я нажимаю свой хэш на массив
push(@switch_ports, %port)
но если я напечатаю @switch_ports
Я просто вижу
data10data20changed0
поэтому просто кажется, что они добавляются к массиву (присоединяются к ним)
и если я попробую и зациклирую массив и распечатаю ключи, он также терпит неудачу.
Я думаю, что я задерживаюсь, так сильно сломал себе голову в стол.
1 - Можете ли вы сохранить хэш в массиве?
2 - У вас есть массив хэшей?
Попытка получить...
switchports
0
data1
data2
changed
1
data1
....
Таким образом,
foreach $port (@switchport) {
print $port['data1']
}
вернет все данные1 для всех хэшей в массиве.
Да, я терпеть неудачу в Perl
Ответы
Ответ 1
В Perl элементы массива и хэша должны быть единственным значением. До Perl 5.0 не было (простого) способа делать то, что вы хотите.
Однако в Perl 5 теперь вы можете использовать ссылку на свой хеш. Ссылка - это просто ячейка памяти, в которой хранится элемент. Чтобы получить ссылку, вы устанавливаете обратную косую черту перед переменной:
use feature qw(say);
my $foo = "bar";
say $foo; #prints "bar"
say \$foo; #prints SCALAR(0x7fad01029070) or something like that
Таким образом:
my @switch_ports = ();
my %port = ( data1 => 0, data2 => 0, changed => 0 );
my $port_ref = \%port;
push( @switch_ports, $port_ref );
И вам не нужно создавать $port_ref
:
my @switch_ports = ();
my %port = ( data1 => 0, data2 => 0, changed => 0 );
push( @switch_ports, \%port );
Чтобы получить фактическое значение ссылки, просто верните символ вперед:
#Remember: This is a REFERENCE to the hash and not the hash itself
$port_ref = $switch_ports[0];
%port = %{$port_ref}; #Dereferences the reference $port_ref;
print "$port{data1} $port{data2} $port{changed}\n";
Еще один ярлык:
%port = %{$port[0]}; #Dereference in a single step
print "$port{data1} $port{data2} $port{changed}\n";
Или, даже короче, разыгрывать, как вы идете:
print ${$port[0]}{data1} . " " . ${$port[0]}{data2} . " " . ${$port[0]}{changed} . "\n";
И немного синтаксического подсластителя. Это означает то же самое, но его легче читать:
print $port[0]->{data1} . " " . $port[0]->{data2} . " " . $port[0]->{changed} . "\n";
Взгляните на Perldoc perlreftut и perlref. Первый - это учебник.
Ответ 2
При попытке:
%port = (data1 => 0, data2 => 0, changed => 0);
push @switch_ports, %port;
Что действительно происходит:
push @switch_ports, "data1", 0, "data2", 0, "changed", 0;
Поскольку массивы и хэши будут автоматически разбиваться на свои элементы при использовании в контексте списка.
Если вы хотите создать 50 экземпляров хэша, не рекомендуется использовать ссылку на существующий хеш, как предложили другие, так как это создаст только 50 разных ссылок на один и тот же хеш. Который будет сбой и ожог по понятным причинам.
Вам нужно что-то вроде:
push @array, { data1 => 0, data2 => 0, changed => 0 } for 1 .. 50;
Что добавит 50 уникальных анонимных хэшей в массив. Скобки означают построение анонимного хэша и возвращает ему скалярную ссылку.
ETA: Ваш пример доступа к этим данным неверен.
foreach $port (@switchport) {
print $port['data1']; # will use @port, not $port
}
Использование индекса для скалярной переменной попытается получить доступ к массиву в этом пространстве имен, а не скаляре. В perl допустимо иметь две отдельные переменные $port
и @port
. Кронштейны используются для массивов, а не для хешей. При использовании ссылок вам также необходимо использовать оператор стрелки: $port->{data1}
. Следовательно:
for my $port (@switchport) {
print $port->{data1};
}
Ответ 3
Вы можете сохранить ссылку на хеш в массиве:
push @switchport, \%port; # stores a reference to your existing hash
или
push @switchport, { %port }; # clones the hash so it can be updated separately
Затем повторите, скажем,
foreach my $port (@switchport) {
print $port->{'data1'}; # or $$port{'data1'}
}
См. man perlref
.
Ответ 4
Чтобы упростить для тех, кто использует этот вопрос, найти общий подход - как в заголовке. Тема Mysql:
my @my_hashes = ();
my @$rows = ... # Initialize. Mysql SELECT query results, for example.
if( @$rows ) {
foreach $row ( @$rows ) { # Every row to hash, every hash to an array.
push @my_hashes, {
id => $row->{ id },
name => $row->{ name },
value => $row->{ value },
};
}
}
Чтобы запрограммировать и распечатать:
for my $i ( 0 .. $#my_hashes ) {
print "$my_hashes[$i]{ id }\n ";
print "$my_hashes[$i]{ name }\n ";
print "$my_hashes[$i]{ value }\n ";
}
или
for my $i ( 0 .. $#my_hashes ) {
for my $type ( keys %{ $my_hashes[$i] } ) {
print "$type=$my_hashes[$i]{$type} ";
}
}