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

I cannnot delete the values from a hash. For example, If I already processed New York City, I want to remove New York City from the hash. Can someone help? I was going to add a new value and set it to 1 for the cities I printed/ processed. The code below does not work and I don't know why.
my $location_hash = get_location(\*ZIPS); my $cat_hash = get_categories (\*SICS); for my $city ( keys %$location_hash ) { printf "%s %s %s\n", $city, $location_hash->{ $city }->{ 'ST' }, $l +ocation_hash->{ $city }->{ 'ZIP' } ; for my $cat ( keys %$cat_hash) { printf "%s %s\n", $cat, $cat_hash->{ $cat }->{ 'NUM' } ; . . . delete ($location_hash->{ $city }) ; ### This is wha +t I want.... Does not work delete ($location_hash->{ $city }->{ 'ZIP' } ); ### Does not wo +rk delete ($cat_hash->{ $cat }->{ 'NUM' }); ### Does not wo +rk delete ($cat_hash->{ $cat }); ### This is wha +t I want.... Does not work } # for my $cat ( keys %$cat_hash) } # for my $city ( keys %$location_hash ) {

Replies are listed 'Best First'.
Re: How can I delete a key' value from a hash
by GrandFather (Saint) on Jan 07, 2007 at 23:17 UTC

    For what value of "does not work"? Could it be that deleting the city then revivfying it by "deleting" the (non-existant) ZIP field is causing you grief? Consider:

    use strict; use warnings; use Data::Dump::Streamer; my $location_hash = { 'New York' => {ZIP => '123-456-789'}, 'Dunedin' => {ZIP => '9001'} }; for my $city ( keys %$location_hash ) { print "$city $location_hash->{ $city }->{ZIP}\n"; delete ($location_hash->{ $city }); delete ($location_hash->{ $city }->{ 'ZIP' } ); } Dump $location_hash;

    Prints:

    Dunedin 9001 New York 123-456-789 $HASH1 = { Dunedin => {}, "New York" => {} };

    You will note that the process of referencing the ZIP key in the second delete autovivifies the city key that you had just deleted. The first delete works and does everything required. The second delete is not required and is likely what is causing you confusion.


    DWIM is Perl's answer to Gödel
      I had to remove the delete for deleting the category. I guess I was getting tired. Thanks
Re: How can I delete a key' value from a hash
by ysth (Canon) on Jan 07, 2007 at 23:10 UTC
    What do you mean "does not work"? Didn't run it myself, but it looks ok, other than deleting the city at the end of the inner loop (instead of the outer loop), when you presumably aren't quite done with it, and not having the categories available anymore when you process the second city.

    Maybe you'd better explain why you want to delete them?

      Oh, good catch. I should not be deleting both inside of the inner loop! Thanks! I am trying to remove the values after processing because, I can possibly receive an error from this program and I need to know which cities I processed when the error occurred. So, I wont process the same cities again.
      It appears that it will delete the zip code and state but not the city.
      printf "Before deleting: city= %s state=%s zip= %s\n", $city , $location_hash->{ $city }->{ 'ST' }, $location_hash->{ $city }->{ 'ZIP' }; delete ($location_hash->{ $city }); delete ($location_hash->{ $city }->{ 'ST' }) ; delete ($location_hash->{ $city }->{ 'ZIP' }) ; printf "After deleting: city= %s state=%s zip= %s\n", $city, $location_hash->{ $city }->{ 'ST' }, $location_hash->{ $city }->{ 'ZIP' };

      Output:

      Before deleting: city= Lucketts state=VA zip= 20176 After deleting: city= Lucketts state= zip=
      Ok, I feel like an idiot ... lol It kept printing $city because it was NOT in the hash. $city was declared above. I almost did not admit it but I wanted you all to get a good laugh :) new code:
      for my $city ( keys %$location_hash ) { . . . printf "Before deleting: state=%s zip= %s\n", $location_hash->{ $city }->{ 'ST' }, $location_hash->{ $city }->{ 'ZIP' }; delete ($location_hash->{ $city }); ### delete ($location_hash->{ $city }->{ 'ST' }) ; ### delete ($location_hash->{ $city }->{ 'ZIP' }) ; printf "After deleting: state=%s zip= %s\n", $location_hash->{ $city }->{ 'ST' }, $location_hash->{ $city }->{ 'ZIP' }; } end for loop
      Output:
      Before deleting: state=VA zip= 20176 After deleting: state= zip= Before deleting: state=VA zip= 20176 After deleting: state= zip=
      Everyone, thanks for your help. Sometimes it helps to have someone to talk to about it and as you explain it you think, "Dah."

        Just for your information:

        printf "After deleting: state=%s zip= %s\n", $location_hash->{ $city }->{ 'ST' }, $location_hash->{ $city }->{ 'ZIP' };

        This code will re-create the key $city} in %$location_hash. $location_hash->{$city} has to exists before it can look up ST and/or ZIP. (autovivication)

        Another note: $location_hash->{$city}->{'ST'} is the same as: $location_hash->{$city}{'ST'} which is the same as: <code>$location_hash->{$city}{ST}

Re: How can I delete a key' value from a hash
by OfficeLinebacker (Chaplain) on Jan 07, 2007 at 23:35 UTC

    Isn't this the classic "operating on a {data structure} inside a loop that iterates through the elements of that {data structure}" problem?

    How do you know it's not working? Are you checking after the loop finishes? Are you sure the loop is iterating over everything you think it is?

    In other words, where is the code you are using that verifies that the code is indeed not doing what you want?

    UPDATE: While I'd still like to know the answers to the questions above, I like GrandFather's tack better. I was not aware of/thinking about the autovivification issue. I had assumed that you originally tried the first delete only, and subsequently added the other delete statements as debugging tools.

    In any case, I think it would give monks a better chance to help if you showed more of your code and/or exlained your procedures better. And I don't mean to imply anything with the above questions; I really am wondering.


    I like computer programming because it's like Legos for the mind.
      Thanks for your help.
Re: How can I delete a key' value from a hash
by roman (Monk) on Jan 08, 2007 at 11:15 UTC
    As you probably got, with
    delete ($location_hash->{ $city }) ; delete ($location_hash->{ $city }->{ 'ZIP' } );

    you delete the $city key and immediately create it again with value being the reference to empty hash. In the argument of second delete you treat $location_hash-{$city} as hash reference and Perl is "clever enough" to create it for you. So you end up with new ($city => {}) pair in %{%location_hash}.

    I personally dislike this automatic structures creation (it affects arrays also) and believe that decent and clearly read operation should not modify your data but raise an exception instead because you are treating undefined value as hash reference.

    Nevertheless, it can be useful for you to know, that delete returns the value deleted

    my $city_ref = delete ($location_hash->{$city}); delete($city_ref->{'ZIP'});