17

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?

2
  • 9
    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? Commented Sep 28, 2010 at 10:45
  • The hash is a global that I create near the beginning of my program after all checks and balances. It is modified with different subroutines until I assign the final version into an array. Given this flow, unless I am missing something, I believe it is easier for me to 'reset' this particular hash after assigning it to the array than it is to recreate it with a my statement. (It is possible that I am overlooking an XY problem since I did not know how to do something like reset a hash) Commented Sep 29, 2010 at 2:14

7 Answers 7

38

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.

Sign up to request clarification or add additional context in comments.

4 Comments

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.
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.
Now I see the difference. Alright, I will have to use Devel::Peek to see which is more efficient for my use case.
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.
7

How about

%hash = ();

Comments

5

You can use undef:

undef %hash;

Comments

2

You can do:

%hash = ();

Comments

2

Use

%hash = ();

1 Comment

With my there, you're actually creating a new hash unrelated to the existing one, not clearing out the old hash.
1

%hash = (); must work

Comments

0

Since the OP asked for a one liner that works with use strict and warnings

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.