I have an array like so,
@switch_ports = ()
and then want to add 50 instances of this hash, to the switch_ports array
%port = (data1 => 0, data2 => 0, changed => 0)
however, if I push my hash to the array
push(@switch_ports, %port)
but if I do print @switch_ports I just see
data10data20changed0
so it just seems to be added them to the array, (joining them) and if I try and loop the array and print the keys, it also fails.
I think i am going retarded from smashed my head into the desk so hard.
1 - Can you store a hash in an array?
2 - Can you have an array of hashes?
Trying to get...
switchports 0 data1 data2 changed 1 data1 ....
thus
foreach $port (@switchport) { print $port['data1'] }
would return all of the data1 for all of the hashes in the array.
Yes, I fail at Perl
While an array can be used to construct hash tables, array indexes its elements using integers. However, if we want to store data and use keys other than integer, such as 'string', we may want to use dictionary. Dictionaries in Python are implemented using hash tables.
Creating an array of hashes You are allowed to create an array of hashes either by simply initializing array with hashes or by using array. push() to push hashes inside the array. Note: Both “Key” and :Key acts as a key in a hash in ruby.
To append a new value to the array of values associated with a particular key, use push : push @{ $hash{"a key"} }, $value; The classic application of these data structures is inverting a hash that has many keys with the same associated value. When inverted, you end up with a hash that has many values for the same key.
In Ruby, a hash is a collection of key-value pairs. A hash is denoted by a set of curly braces ( {} ) which contains key-value pairs separated by commas. Each value is assigned to a key using a hash rocket ( => ). Calling the hash followed by a key name within brackets grabs the value associated with that key.
In Perl, array and hash members must be a single value. Before Perl 5.0, there was no (easy) way to do what you want.
However, in Perl 5 you can now use a reference to your hash. A reference is simply the memory location where the item is being stored. To get a reference, you put a backslash in front of the variable:
use feature qw(say); my $foo = "bar"; say $foo; #prints "bar" say \$foo; #prints SCALAR(0x7fad01029070) or something like that
Thus:
my @switch_ports = (); my %port = ( data1 => 0, data2 => 0, changed => 0 ); my $port_ref = \%port; push( @switch_ports, $port_ref );
And, you don't have to create $port_ref
:
my @switch_ports = (); my %port = ( data1 => 0, data2 => 0, changed => 0 ); push( @switch_ports, \%port );
To get the actual value of the reference, simply put the symbol back on front:
#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";
Another shortcut:
%port = %{$port[0]}; #Dereference in a single step print "$port{data1} $port{data2} $port{changed}\n";
Or, even shorter, dereferencing as you go along:
print ${$port[0]}{data1} . " " . ${$port[0]}{data2} . " " . ${$port[0]}{changed} . "\n";
And a little syntactic sweetener. It means the same, but is easier to read:
print $port[0]->{data1} . " " . $port[0]->{data2} . " " . $port[0]->{changed} . "\n";
Take a look at Perldoc's perlreftut and perlref. The first one is a tutorial.
When you try:
%port = (data1 => 0, data2 => 0, changed => 0); push @switch_ports, %port;
What really happens is:
push @switch_ports, "data1", 0, "data2", 0, "changed", 0;
Because arrays and hashes will automatically break into their elements when used in list context.
When you want to create 50 instances of a hash, it is not a good idea to use a reference to an existing hash as others have suggested, as that will only create 50 different references to the same hash. Which will crash and burn for obvious reasons.
What you need is something like:
push @array, { data1 => 0, data2 => 0, changed => 0 } for 1 .. 50;
Which will add 50 unique anonymous hashes to the array. The braces denotes construction of an anonymous hash, and returns a scalar reference to it.
ETA: Your example of how to access this data is wrong.
foreach $port (@switchport) { print $port['data1']; # will use @port, not $port }
Using a subscript on a scalar variable will attempt to access an array in that namespace, not a scalar. In perl, it is valid to have two separate variables $port
and @port
. Brackets are used for arrays, not hashes. When using references, you also need to use the arrow operator: $port->{data1}
. Hence:
for my $port (@switchport) { print $port->{data1}; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With