Добавление хэша в массив

у меня такой массив,

@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']
}

вернет все data1 для всех хэшей в массиве.

Да, я терплю неудачу в Perl

4 ответов


в Perl члены array и hash должны иметь одно значение. До 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. Первый-это учебник.


когда вы пытаетесь:

%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};
}

вы можете сохранить ссылка хэш в массив:

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.


упростить для тех, кто использует этот вопрос, чтобы найти общий подход - как в заголовке вопроса. Тема 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} ";
}

}