Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Re: Push array to hash

by haukex (Archbishop)
on Jun 25, 2020 at 07:03 UTC ( [id://11118491]=note: print w/replies, xml ) Need Help??


in reply to Push array to hash

The first structure appears just fine, but subsequent pushes only show as "${$VAR1}->[0]" - not sure why?

As BillKSmith mentioned, what's going on here is that you have one hash %lag_detail, and every time you push a reference to that hash onto the array, you're pushing a reference to the same one hash. This also means that when you write %lag_detail = ( ... );, you're resetting that one hash, and therefore every reference to the hash will reflect that change, which is unlikely to be what you want. That's what ${$VAR1}->[0] means: Data::Dumper is trying to tell you that the other elements of the array refer to the exact same data structure.

In essence, this is what's going on - note how both times, a reference to the same hash is pushed onto the array:

use warnings; use strict; use Data::Dumper; my @array; my %hash = ( abc=>123 ); push @array, \%hash; %hash = ( def=>456 ); push @array, \%hash; print Dumper(\@array); print $array[1]{def}, "\n"; # ok print $array[0]{abc}, "\n"; # nope! hash was cleared! __END__ $VAR1 = [ { 'def' => 456 }, $VAR1->[0] ]; 456 Use of uninitialized value in print at test.pl line 13.

There are a couple of ways to fix this. The one that I think is probably most applicable in this case is to change from using a hash %lag_detail to a reference to an anonymous hash (hashref), as in:

my $lag_detail; foreach my $line ( split( /\n/, $c ) ) { if ( $line =~ m/someregex/ ) { if ( exists $lag_detail->{ports} ) { push( @{ $self->{lags} }, $lag_detail ); } $lag_detail = { lagid => $lag, lagdesc => $4, operationstate => $3, adminstate => $2 }; } }

The reason this works is that with $lag_detail = { ... }, you're actually allocating a new anonymous hash every time and getting a reference to it. See perlreftut and perlref if you're unsure about some of the details of references.

Just for completeness, in addition to the (shallow) copying of the hash that BillKSmith suggested, a very common solution to this problem is to define the hash inside the loop, which also gets you a new hash on every iteration of the loop:

foreach my $line ( split( /\n/, $c ) ) { my %lag_detail; ...

However, since it looks to me like you're probably parsing a multiline data strucutre and don't want to push a record onto the array until it is complete, I think this is unlikely to be the correct fix in your case.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11118491]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others lurking in the Monastery: (3)
As of 2024-04-25 23:39 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found