http://www.perlmonks.org?node_id=315063

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

hello guys!

I have a hash of hashes, for example:
%hash = { abc => { def => 1, }, ghi => { jkl => 1, }, };
What happen if I do:
delete($hash{abc}{def});
am I staying with?:
%hash = { abc => undef, ghi => { jkl => 1, mno => 1, }, };
That was the first question.
My second one is, I'm looping over the hash and delete keys as shown above if fulfilled a condition. If the ansewer to the first question is yes, is there a short way to delete also the first level key ('abc' in the example) when deleted all second level keys under it. In the example, when performing the above delete, i would have like to stay with:?:
%hash = { ghi => { jkl => 1, mno => 1, }, };
Thanks

Replies are listed 'Best First'.
Re: Deleting hash entry
by broquaint (Abbot) on Dec 16, 2003 at 15:05 UTC
    Firstly, the first level of that hash assignment should be using parens and not curly braces. Now in answer to your first question, you will delete the def key in the hash pointed to by $hash{abc}. As for the second question, just test that the hash is empty with the use of keys in a scalar context e.g
    use Data::Dumper; my %hash = ( abc => {}, ghi =>{ qw/ two key value pairs / } ); print "before: ", Dumper \%hash; delete $hash{abc} unless keys %{ $hash{abc} }; print "after: ", Dumper \%hash; __output__ before: $VAR1 = { 'abc' => {}, 'ghi' => { 'two' => 'key', 'value' => 'pairs' } }; after: $VAR1 = { 'ghi' => { 'two' => 'key', 'value' => 'pairs' } };
    HTH

    _________
    broquaint

Re: Deleting hash entry
by talexb (Chancellor) on Dec 16, 2003 at 15:05 UTC
      What happen if I do: delete($hash{abc}{def});

    I would hazard a guess that the hash key value pair you have specified would be deleted. What happens when you try it? (I did not.)

      .. is there a short way to delete also the first level key ('abc' in the example) when deleted all second level keys under it.

    Sure, I would use delete($hash{abc}) This would delete the top level and everything underneath it.

    And now, an editorial comment ..

    Please, I would strongly urge you (and anyone else) to go into the Perl debugger and try these things out rather than posting here. Wait until you've tried a bunch of things and are well and truly stumped. We love interesting, challenging questions. Questions that show no effort leave us uninspired.

    --t. alex
    Life is short: get busy!
      Alex, your forgetting the usefulness of this forum as a reference.
Re: Deleting hash entry
by tcf22 (Priest) on Dec 16, 2003 at 15:01 UTC
    I think you meant:
    %hash = ( abc => { def => 1, }, ghi => { jkl => 1, }, );
    Hashes use (), hash refs use {}.

    delete($hash{abc}{def});
    should work for deleting a second level key.

    - Tom

Re: Deleting hash entry
by Aragorn (Curate) on Dec 16, 2003 at 15:22 UTC
    First of all, the notation %hash = { ... is wrong. You either assign a hash with %hash = ( ... or a hash reference with $hash = { .... Watch those parentheses and curly braces. See perlreftut and perlref for more information.

    As for deleting:

    #!/usr/bin/perl use Data::Dumper; $hash = { abc => { 'def' => 1, }, ghi => { jkl => 1, mno => 1, }, }; print Dumper(\$hash); delete($hash->{abc}->{def}); print Dumper(\$hash); __END__ $VAR1 = \{ 'abc' => { 'def' => 1 }, 'ghi' => { 'mno' => 1, 'jkl' => 1 } }; $VAR1 = \{ 'abc' => {}, 'ghi' => { 'mno' => 1, 'jkl' => 1 } };
    The second question: I don't know :-). Having an undefined hash value is perfectly valid, so the upper level is not automatically deleted when the lower level becomes undefined. You could add a statement like delete $hash->{$key} if not keys %{$hash->{$key}}. This deletes the key only if the hash it references is empty.

    Arjen