in reply to Re^2: Using grep to remove array element from HoAoH leaving empty array-hash element
in thread Using grep to remove array element from HoAoH leaving empty array-hash element

Err. There is an empty hash at the bottom of your before-grep dump as well. Is that a posting mistake, or is it actually there during your code's execution?

Makeshifts last the longest.

  • Comment on Re^3: Using grep to remove array element from HoAoH leaving empty array-hash element

Replies are listed 'Best First'.
Re^4: Using grep to remove array element from HoAoH leaving empty array-hash element
by Popcorn Dave (Abbot) on Aug 11, 2004 at 19:51 UTC
    Good catch! That is being added when the program runs, it wasn't a posting error. Looks like I need to get my eyes checked. :)

    I've narrowed it down to this bit of code, but for the life of me I can't see how or why it would be adding the empty hash. I've also noticed that I lose the data in the 1958 array after the first iteration of the for loop.

    Basically I'm going through each of the years I have data for and seeing if my match appears in any of those years. If it does, it gets put in to @res for display in a list.

    Here's the offending code:

    for $find qw((1958 1959 1960 1961 1962 1963 1964)){ $index = 0; # index is defined to go down the array of each year while (defined $bros->{$find}->[$index]->{$key}){ if ($bros->{$find}->[$index]->{$key} =~ /$data/i){ # since we found one, we push the brothers data structure a +nd # year of graduation in to the results hash push (@res,{brother => $bros->{$find}->[$index], year => $f +ind}); } # end if $index++; } # end while } # end find

    I'd appreciate anything you could suggest as to where this might be adding the empty hash!

    Useless trivia: In the 2004 Las Vegas phone book there are approximately 28 pages of ads for massage, but almost 200 for lawyers.

      You are running into autovivification.

      $ perl -le'undef $_; defined $_->{0}; print $_' HASH(0x813f1c8)

      Whenever you try to dereference an undefined value, Perl will helpfully summon an anonymous data type of the corresponding type and store it there. In your case, the culprit is probably

      while( defined $bros->{ $find }->[ $index ]->{ $key } ) { # ... }

      If you use exists there instead, your ghost hashes should go away. Actually, no, they won't. The hash is summoned by the mere attempt at dereferencing. You have to make sure that $bros->{ $find }->[ $index ] exists before attempting a dereference:

      while( ref $bros->{ $find }->[ $index ] and defined $bros->{ $find }->[ $index ]->{ $key } ) { # ... }

      However, in Perl, it's almost always a mistake to use a counter variable such as $index when you only ever use it as an index into a single structure. This is one of the red flags mentioned in Mark-Jason Dominus' excellent Program Repair Shop and Red Flags article series. You could have avoided the issue altogether by rewriting your inner loop to a foreach:

      for my $year ( qw( 1958 1959 1960 1961 1962 1963 1964 ) ) { for my $film ( @{ $bros->{ $year } } ) { push @res, { brother => $film, year => $year } if $film->{ $key } =~ /$data/i; } }

      Depending on taste that can be transformed to a grep:

      for my $year ( qw( 1958 1959 1960 1961 1962 1963 1964 ) ) { push @res, ( map +{ brother => $_, year => $year }, grep $_->{ $key } =~ /$data/i, @{ $bros->{ $year } }, ); }

      Makeshifts last the longest.