J'ai un tableau comme ça,
@switch_ports = ()
puis souhaitez ajouter 50 instances de ce hachage, au tableau switch_ports
%port = (data1 => 0, data2 => 0, changed => 0)
cependant, si je pousse mon hachage sur le tableau
Push(@switch_ports, %port)
mais si j'imprime @switch_ports, je vois juste
data10data20changed0
il semble donc simplement les ajouter au tableau (les joindre) et si j'essaie de boucler le tableau et d'imprimer les clés, il échoue également.
Je pense que je vais être retardé de m'être fracassé la tête contre le bureau si fort.
1 - Pouvez-vous stocker un hachage dans un tableau?
2 - Pouvez-vous avoir un tableau de hachages?
Essayer d'obtenir...
switchports
0
data1
data2
changed
1
data1
....
donc
foreach $port (@switchport) {
print $port['data1']
}
retournerait toutes les données1 pour tous les hachages du tableau.
Oui, j'échoue chez Perl
En Perl, les membres de tableau et de hachage doivent être une seule valeur. Avant Perl 5.0, il n'y avait pas de moyen (facile) de faire ce que vous vouliez.
Cependant, dans Perl 5, vous pouvez désormais utiliser une référence à votre hachage. Une référence est simplement l'emplacement de mémoire où l'élément est stocké. Pour obtenir une référence, vous mettez une barre oblique inverse devant la variable:
use feature qw(say);
my $foo = "bar";
say $foo; #prints "bar"
say \$foo; #prints SCALAR(0x7fad01029070) or something like that
Donc:
my @switch_ports = ();
my %port = ( data1 => 0, data2 => 0, changed => 0 );
my $port_ref = \%port;
Push( @switch_ports, $port_ref );
Et vous n'avez pas besoin de créer $port_ref
:
my @switch_ports = ();
my %port = ( data1 => 0, data2 => 0, changed => 0 );
Push( @switch_ports, \%port );
Pour obtenir la valeur réelle de la référence, il suffit de remettre le symbole devant:
#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";
Un autre raccourci:
%port = %{$port[0]}; #Dereference in a single step
print "$port{data1} $port{data2} $port{changed}\n";
Ou, encore plus court, déréférencer au fur et à mesure:
print ${$port[0]}{data1} . " " . ${$port[0]}{data2} . " " . ${$port[0]}{changed} . "\n";
Et un peu d'édulcorant syntaxique. Cela signifie la même chose, mais est plus facile à lire:
print $port[0]->{data1} . " " . $port[0]->{data2} . " " . $port[0]->{changed} . "\n";
Jetez un oeil à perlreftut et perlref de Perldoc. Le premier est un tutoriel.
Lorsque vous essayez:
%port = (data1 => 0, data2 => 0, changed => 0);
Push @switch_ports, %port;
Ce qui se passe vraiment, c'est:
Push @switch_ports, "data1", 0, "data2", 0, "changed", 0;
Parce que les tableaux et les hachages vont se casser automatiquement dans leurs éléments lorsqu'ils sont utilisés dans le contexte de la liste.
Lorsque vous souhaitez créer 50 instances d'un hachage, ce n'est pas une bonne idée d'utiliser une référence à un hachage existant comme d'autres l'ont suggéré, car cela ne créera que 50 références différentes au même hachage. Qui va planter et brûler pour des raisons évidentes.
Ce dont vous avez besoin est quelque chose comme:
Push @array, { data1 => 0, data2 => 0, changed => 0 } for 1 .. 50;
Ce qui ajoutera 50 hachages anonymes uniques au tableau. Les accolades dénotent la construction d'un hachage anonyme et lui retournent une référence scalaire.
ETA: Votre exemple d'accès à ces données est faux.
foreach $port (@switchport) {
print $port['data1']; # will use @port, not $port
}
L'utilisation d'un indice sur une variable scalaire tentera d'accéder à un tableau dans cet espace de noms, pas un scalaire. En Perl, il est valide d'avoir deux variables distinctes $port
et @port
. Les parenthèses sont utilisées pour les tableaux, pas les hachages. Lorsque vous utilisez des références, vous devez également utiliser l'opérateur de flèche: $port->{data1}
. Par conséquent:
for my $port (@switchport) {
print $port->{data1};
}
Vous pouvez stocker un référence à un hachage dans un tableau:
Push @switchport, \%port; # stores a reference to your existing hash
ou
Push @switchport, { %port }; # clones the hash so it can be updated separately
Ensuite, répétez avec, disons,
foreach my $port (@switchport) {
print $port->{'data1'}; # or $$port{'data1'}
}
Voir man perlref
.
Pour simplifier pour ceux qui utilisent cette question pour trouver une approche générale - comme dans la question de titre. Thème 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 },
};
}
}
Pour boucler et imprimer:
for my $i ( 0 .. $#my_hashes ) {
print "$my_hashes[$i]{ id }\n ";
print "$my_hashes[$i]{ name }\n ";
print "$my_hashes[$i]{ value }\n ";
}
ou
for my $i ( 0 .. $#my_hashes ) {
for my $type ( keys %{ $my_hashes[$i] } ) {
print "$type=$my_hashes[$i]{$type} ";
}
}