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

Fellow monks,

I'm using grep to remove an array element from a HoAoH and I assumed that if I deleted the array element, that the hash element would disappear as well. However, I'm getting a warning of "Use of uninitialized value in string eq" which I think is being generated because of the empty hash element in the array, but I can't figure out why grep would be looking at that after it has been eliminated.

This is the code I'm using:

@{$bros->{$yr}} = grep {!($_->{last} eq $last)} @{$bros->{$yr}};

And my data structure is:

$bros = { '1958' => [{'first' =>, 'last' =>, etc...], '1959' => [{..}] +, etc..}
where the person's data is stored in a hash in the year array.

My question is, how to eliminate the warning error and eliminate the empty hash element in the array. I'm not exactly clear on how to undef the array element in the grep.

Would it be better to assign the anonymous structure to an array and then grep a physical array? I would think I would run in to the same problem.

Thanks in advance!

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

Replies are listed 'Best First'.
Re: Using grep to remove array element from HoAoH leaving empty array-hash element
by ikegami (Patriarch) on Aug 10, 2004 at 20:00 UTC

    I don't think you're on the right track with the hash element not disappearing idea.

    There are three possibilities:

    1) $last is not defined. Easily verifiable with die("\$last is undef.\n") unless (defined($last));.

    2) The key last is not found in %$_ for some element $_ of @{$bros->{$yr}}, as in the following structure:

    $bros = { '1976' => [ { 'first' => 'Eric', # oops! no 'last'! }, } };

    3) $_->{last} is not defined for some element $_ of @{$bros->{$yr}}, as in the following structure:

    $bros = { '1976' => [ { 'first' => 'Eric', 'last' => undef, # oops! no value for 'last'! }, ], };

    For (2) and (3), printing out $bros or @{$bros->{$yr}} with the help of Data::Dumper might help you locate the record with the missing 'last' or the one which has undef for value.

      I think you're on to something with 2 and 3. Take a look at my reply and you'll see the Data::Dumper results. I'm getting an empty hash after the grep which appears to be appended to the end of the array. I think that is where grep is throwing the error, but I'm stumped on how to rectify that.

      Useless trivia: In the 2004 Las Vegas phone book there are approximately 28 pages of ads for massage, but almost 200 for lawyers.
        It's not the 'after' that's important. The warning is your grep condition telling you the data is wrong (i.e. different than expected) before grep is called. Data::Dumper shows us this bad data: the extra "{}" at the end of the list in the 'before' dump. What you must do now is figure out how that extra (fieldless) record is being added to your 'database'.
Re: Using grep to remove array element from HoAoH leaving empty array-hash element
by Aristotle (Chancellor) on Aug 10, 2004 at 18:22 UTC

    The code you show looks fine. You haven't told us enough. Do you get the warning for the grep line? Can you show us the code that deletes the "array element"?

    Makeshifts last the longest.

      As far as I am able to tell, the warning is being generated in the grep. Splitting it in to seperate lines in the code said that the warning was in the second occurence of @{$bros->{$yr}} - the array being grepped.

      The code I'm using to initialize the whole structure is:

      my $bros= {'1958' => [], '1959' => [], '1960' => [], '1961' => [], '1962' => [], '1963' => [], '1964' => []};

      since I was lazy and wanted to pre-build my data structure.

      Here's the Data::Dumper listing of before and after the grep:

      before grep: $VAR1 = \[ { 'state' => 'OR', 'last' => 'Bertelson', 'first' => 'Gordon', }, { 'state' => '', 'last' => 'Blaise', 'first' => 'Larry', }, { 'state' => 'OR', 'last' => 'Douda', 'first' => 'Henry B.', }, { 'state' => 'NSW 221', ' => 'Australia', 'last' => 'McHolick', 'first' => 'Dwane', }, { 'state' => 'OR', 'last' => 'Murray', 'first' => 'Melvin', }, { 'state' => 'OR', 'last' => 'Perry', 'first' => 'Larry', }, { 'state' => '', 'last' => 'Peterson', 'first' => 'Ken', }, { 'state' => 'OR', 'last' => 'Rianda', 'first' => 'Dave', }, { 'state' => 'OR', 'last' => 'Steffanoff', 'first' => 'Nick', }, { 'state' => 'CA', 'last' => 'Turner', 'first' => 'Paul', }, { 'state' => 'OR', 'last' => 'Wilson', 'first' => 'Dick', }, {} ]; after grep: $VAR1 = \[ { 'state' => 'OR', 'last' => 'Bertelson', 'first' => 'Gordon', }, { 'state' => '', 'last' => 'Blaise', 'first' => 'Larry', }, { 'state' => 'OR', 'last' => 'Douda', 'first' => 'Henry B.', }, { 'state' => 'NSW 221', 'last' => 'McHolick', 'first' => 'Dwane', }, { 'state' => 'OR', 'last' => 'Murray', 'first' => 'Melvin', }, { 'state' => 'OR', 'last' => 'Perry', 'first' => 'Larry', }, { 'state' => '', 'last' => 'Peterson', 'first' => 'Ken', }, { 'state' => 'OR', 'last' => 'Rianda', 'first' => 'Dave', }, { 'state' => 'OR', 'last' => 'Steffanoff', 'first' => 'Nick', }, { 'state' => 'OR', 'last' => 'Wilson', 'first' => 'Dick', }, {} <- here's the empty hash ];

      so you can see exactly what I'm saying by there's an empty hash where Paul Turner's information was.

      As far as removing the element, I thought using the negative grep would find everything that didn't match what I wanted and put it in the array. I thought I was on the right track with the negative grep but I don't understand the empty hash in the array still being there.

      My assumption is that grep is choking for whatever reason on that empty hash, so is a negative grep the way to go here?

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

        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.