http://qs321.pair.com?node_id=11135854

MrSnrub has asked for the wisdom of the Perl Monks concerning the following question:

I am using perl 5.10. I am iterating through a for loop. inside that loop I am trying to add an array to a list and then clear the array so I can add different items on the next iteration of the for loop. But when I clear the array, it's clearing the array that I already added to the hash. Here is my code:
      # WRONG!!! This will create a reference (so when we clear it       # a couple lines later everything will be deleted).       # $current_main_record{"role_data"} = \@role_records;         # CORRECT? Recursively copy everything in the entire array,       # so that we can clear it a couple lines down?       # Clear array for next go-round of the loop?.       @role_records = ();
I want $current_main_record(“role_data”) to hold @role_records, an array of hashes. I want to create a new array with the same name, I guess. How do I do that?

Replies are listed 'Best First'.
Re: How to create a new array with the same name as an existing one in a loop?
by hippo (Bishop) on Aug 16, 2021 at 08:35 UTC
    But when I clear the array, it's clearing the array that I already added to the hash.

    But you didn't add the array to the hash, you added a reference to the array. When you change the contents of the array you will see the change whether you look in the array directly or via the reference. See perlreftut for an intro to references and perldsc for more complicated structures.

    Why not build your data directly into $current_main_record{role_data} instead of using an intermediate?


    🦛

Re: How to create a new array with the same name as an existing one in a loop?
by ikegami (Patriarch) on Aug 15, 2021 at 20:42 UTC

    Just create the array in the loop instead of outside the loop.

    my %current_main_record; for my $x (qw(foo bar baz)) { my @role_records; # New array. for my $y (qw(zip zap zop)) { push @role_records, $y; } $current_main_record{"role_data"} = \@role_records; }

    Seeking work! You can reach me at ikegami@adaelis.com

Re: How to create a new array with the same name as an existing one in a loop?
by haj (Vicar) on Aug 15, 2021 at 18:06 UTC

    Just a quick guess: Create a copy to your list instead of a reference:

    $current_main_record{"role_data"} = [@role_records];
      ... = [@role_records];

      MrSnrub: Note that this is a shallow copy.


      Give a man a fish:  <%-{-{-{-<

        how do you do a deep copy? i want to be able to copy everything.
Re: How to create a new array with the same name as an existing one in a loop? (updated)
by AnomalousMonk (Archbishop) on Aug 15, 2021 at 18:04 UTC

    Insofar as I understand what you want to do, this might be one way:

    Win8 Strawberry 5.8.9.5 (32) Sun 08/15/2021 14:00:28 C:\@Work\Perl\monks >perl use strict; use warnings; use Data::Dump qw(dd); my %current_main_record; for my $x (qw(foo bar baz)) { my $ar_role_records; # new array ref. for my $y (qw(zip zap zop)) { push @$ar_role_records, "$x:$y"; } push @{ $current_main_record{'role_data'} }, $ar_role_records; } dd \%current_main_record; ^Z { role_data => [ ["foo:zip", "foo:zap", "foo:zop"], ["bar:zip", "bar:zap", "bar:zop"], ["baz:zip", "baz:zap", "baz:zop"], ], }
    See Perl Data Structures Cookbook.

    Update:

    ... I am trying to add an array to a list ... an array of hashes.
    Maybe this is closer to what you want:
    Win8 Strawberry 5.8.9.5 (32) Sun 08/15/2021 17:43:06 C:\@Work\Perl\monks >perl use strict; use warnings; use Data::Dump qw(dd); my %current_main_record; for my $k (qw(a b c)) { my @role_records; # new array for my $v (qw(Z Y)) { push @role_records, { $k => $v }; } push @{ $current_main_record{'role_data'} }, \@role_records; } dd \%current_main_record; ^Z { role_data => [ [{ a => "Z" }, { a => "Y" }], [{ b => "Z" }, { b => "Y" }], [{ c => "Z" }, { c => "Y" }], ], }


    Give a man a fish:  <%-{-{-{-<

Re: How to create a new array with the same name as an existing one in a loop?
by holli (Abbot) on Aug 15, 2021 at 18:11 UTC
    Ideally you create the array where it is supposed to stay (remember autovivification).
    >perl -MData::Dumper -e "my %hash; push @{ $hash{array} }, 1; push @{ +$hash{array} }, 2; print Dumper \%hash;" $VAR1 = { 'array' => [ 1, 2 ] };


    holli

    You can lead your users to water, but alas, you cannot drown them.
Re: How to create a new array with the same name as an existing one in a loop?
by stevieb (Canon) on Aug 15, 2021 at 17:51 UTC

    This sounds like an X-Y Problem. Please show all your code so we have full context of the situation.

Re: How to create a new array with the same name as an existing one in a loop?
by karlgoethebier (Abbot) on Aug 17, 2021 at 05:11 UTC

    Is this really the structure you want?

    dd \%current_main_record; { role_data => [ [{ a => "Z" }, { a => "Y" }], [{ b => "Z" }, { b => "Y" }], [{ c => "Z" }, { c => "Y" }], ], }

    «The Crux of the Biscuit is the Apostrophe»