How can I reset a hash completely without using a for loop?

16,977

Solution 1

Both %hash = (); and undef %hash; will work, with the difference that the latter will give back some memory to use for other things. The former will keep the memory the things in the hash used before, assuming it'll be used again later anyway, when the hash is being refilled.

You can use Devel::Peek to observe that behaviour:

$ perl -MDevel::Peek -we'my %foo = (0 .. 99); %foo = (); Dump \%foo; undef %foo; Dump \%foo'
SV = IV(0x23b18e8) at 0x23b18f0
  REFCNT = 1
  FLAGS = (TEMP,ROK)
  RV = 0x23acd28
  SV = PVHV(0x23890b0) at 0x23acd28
    REFCNT = 2
    FLAGS = (PADMY,SHAREKEYS)
    ARRAY = 0x23b5d38
    KEYS = 0
    FILL = 0
    MAX = 63
    RITER = -1
    EITER = 0x0
SV = IV(0x23b18e8) at 0x23b18f0
  REFCNT = 1
  FLAGS = (TEMP,ROK)
  RV = 0x23acd28
  SV = PVHV(0x23890b0) at 0x23acd28
    REFCNT = 2
    FLAGS = (PADMY,SHAREKEYS)
    ARRAY = 0x0
    KEYS = 0
    FILL = 0
    MAX = 7
    RITER = -1
    EITER = 0x0

The MAX fields in the PVHVs are the important bit.

Solution 2

How about

%hash = ();

Solution 3

You can use undef:

undef %hash;

Solution 4

Use

%hash = ();

Solution 5

You can do:

%hash = ();
Share:
16,977

Related videos on Youtube

Structure
Author by

Structure

Updated on May 04, 2022

Comments

  • Structure
    Structure about 2 years

    I would like to completely reset my %hash so that it does not contain keys or values at all. I prefer to use a one-liner than have to use a loop.

    So far I have tried:

    %hash = 0;
    %hash = undef;
    

    But these both throw errors in strict mode with warnings enabled, so I wrote a simple for loop to achieve the same thing:

    for (keys %hash) {
        delete $hash{$_};
    }
    

    This works but I would really like to do this with a one-liner. Is there a way to simply reset a hash that I am overlooking?

    • daxim
      daxim almost 14 years
      I'm amazed that noone has unasked the question already. AFAICR I never had the need to reset a hash because with Perl one can have really tight scopes. I instead let variables simply fall out of scope; if in a loop, a new lexical would be created with my near the top. – I think this is an XY problem with room for algorithmic improvement, perhaps give some more context?
  • cjm
    cjm almost 14 years
    With my there, you're actually creating a new hash unrelated to the existing one, not clearing out the old hash.
  • Structure
    Structure almost 14 years
    Thanks for the additional insight. I expect that my hash will never contain the same values when it is re-populated so I will utilize the undef %hash; syntax.
  • user5415701
    user5415701 almost 14 years
    It's not really about what values are stored in the hash, but about how many of them there are. Allocating, freeing, and then allocating some memory again to store values in a hash isn't the fastest thing you can do, so perl makes the assumption that a hash will eventually grow to its original size again, even if it is cleared with %h = (), and keeps the memory required to store as many elements around in the hash unless explicitly asked not to do so. This is not to be confused with the memory your actual values within the hash take up.
  • Structure
    Structure almost 14 years
    Now I see the difference. Alright, I will have to use Devel::Peek to see which is more efficient for my use case.
  • jrockway
    jrockway over 13 years
    Actually, Devel::Peek is not what tells you what's more efficient. That's what your brain is for. If you are clearing a hash that had 65 members and are just going to put 65 members in, then you might as well just reuse the memory. If you are clearing a hash that had over 9000 entries in it, and just want to have three, then sure... time to clear it.