web-dev-qa-db-ja.com

配列にハッシュを追加する

私はそのような配列を持っています、

@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で失敗します

21
Wizzard

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 を見てください。最初のチュートリアルはチュートリアルです。

38
David W.

試すとき:

%port = (data1 => 0, data2 => 0, changed => 0);
Push @switch_ports, %port;

実際に起こることは:

Push @switch_ports, "data1", 0, "data2", 0, "changed", 0;

配列とハッシュは、リストコンテキストで使用すると 要素に自動的に分割される になるためです。

ハッシュの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
}

スカラー変数で添え字を使用すると、スカラーではなく、そのネームスペースのarrayにアクセスしようとします。 Perlでは、2つの別個の変数$portおよび@port。ハッシュではなくブラケットが配列に使用されます。参照を使用する場合は、矢印演算子も使用する必要があります:$port->{data1}。したがって:

for my $port (@switchport) {
    print $port->{data1};
}
9
TLP

参照ハッシュを配列に保存できます:

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
Henning Makholm

見出しの質問のように、この質問を使用して一般的なアプローチを見つけるために簡単にするため。 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} ";
}

}

4
Zon