How can I reset a hash completely without using a for loop?
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 PVHV
s 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 = ();
Related videos on Youtube
Structure
Updated on May 04, 2022Comments
-
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 almost 14 yearsI'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 almost 14 yearsWith
my
there, you're actually creating a new hash unrelated to the existing one, not clearing out the old hash. -
Structure almost 14 yearsThanks 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 almost 14 yearsIt'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 almost 14 yearsNow I see the difference. Alright, I will have to use Devel::Peek to see which is more efficient for my use case.
-
jrockway over 13 yearsActually, 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.