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

Hi, I have an array of hashes that I am looping through. Is it a bad idea to add / modify to the hash when I am inside the loop? Thanks.
use strict; my @people= ( {name=>'Bob'}, {name=>'Carol'} ); foreach my $i ( 0..$#people ) { if ( $people[$i]->{name} eq 'Bob' ) { $people[$i]->{name}='Robert'; # MODIFY $people[$i]->{age}=46; # ADD } }

Replies are listed 'Best First'.
Re: Modifying an array of hashes
by GrandFather (Saint) on Apr 06, 2011 at 21:04 UTC

    There is not problem with doing that. You are not changing the contents of the array, only the contents of hashes referenced by elements of the array.

    A more Perlish way to write the loop is:

    for my $person (@people) { if ($person->{name} eq 'Bob') { $person->{name} = 'Robert'; # MODIFY $person->{age} = 46; # ADD } }
    True laziness is hard work
      And even more Perlish is the use of map, low precedence and, hash slices, and list assignment (untested):
      map {$$_{name} eq 'Bob' and @{$_}{qw{name age}} = qw{Robert 42}}} @peo +ple;
        yuck!
        Yuck indeed. This will not work because
        $$_{name} eq 'Bob' and @{$_}{qw{name age}
        will at best evaluate to '' for non-Bobs.
Re: Modifying an array of hashes
by ikegami (Patriarch) on Apr 06, 2011 at 22:37 UTC

    Adding, replacing or removing elements an array over which you are iterating should be avoided.

    for (@a) { push @a, ...; # XXX Avoid splice @a, ...; # XXX Avoid pop @a; # XXX Avoid }

    Changing the value of an array element is fine, as is changing variables referenced by them

    for my $person (@people) { # Do anything you want to $person # Do anything you want to $person->{whatever} }

    In your code, you are iterating over a list of numbers that you can't even change if you wanted to. There's definitely no harm in that.

Re: Modifying an array of hashes
by Anonymous Monk on Apr 07, 2011 at 01:06 UTC
    Note that each(), if you use that, is a little fragile.