how to check if a hash is empty in perl
Solution 1
if (%hash)
Will work just fine.
From perldoc perldata:
If you evaluate a hash in scalar context, it returns false if the hash is empty. If there are any key/value pairs, it returns true; more precisely, the value returned is a string consisting of the number of used buckets and the number of allocated buckets, separated by a slash.
Solution 2
There was a bug which caused tied hashes in scalar context to always return false. The bug was fixed in 5.8.5. If you're concerned with backwards compatibility that far back I would stick with if( !keys %hash )
. Otherwise use if( !%hash )
as recommended by others.
Solution 3
Simpler:
if (!%hash) {
print "Empty";
}
!
imposes a scalar context, and hash evaluated in a scalar context returns:
-
false if there are zero keys (not defined in the documentation but experimentally returns
0
)
Depending on the version of Perl, either of the following:
-
A string signifying how many used/allocated buckets are used for >0 keys, which will of course be NOT false (e.g. "3/6"). (Non-empty string evaluate to true)
-
The number of keys in the hash (as explained in
perldata
: "As of Perl 5.25 the return was changed to be the count of keys in the hash. If you need access to the old behavior you can use "Hash::Util::bucket_ratio()" instead.")
Solution 4
"Better" is a subjective term. However I would argue that code that is easier to understand can be described as "better". For this reason I conclude that !keys %hash
is better, because everybody writing perl code will know what this code does and that it works. !%hash
is something at least I would have to look up to ensure if it really works or only looks like it would work. (The reason being that the return value of a hash in scalar context is rather confusing while an arrays behavior in scalar context is well known and often used.)
Also, !keys %hash
is safe.
So no, there is no better or safer way to check if a hash is empty.
![Kiran K Telukunta](https://i.stack.imgur.com/TpAjt.png?s=256&g=1)
Kiran K Telukunta
Updated on July 14, 2022Comments
-
Kiran K Telukunta almost 2 years
I use the following code to check if the hash is empty. Is there a better method and is this safe to use?
if (!keys %hash) { print "Empty";}
-
Borodin over 12 yearsNo it doesn't return
"false"
, which would be a true value. It returns zero. -
choroba almost 11 yearsIt seems much slower than
keys %hash
. -
U. Windl almost 3 yearsGood answer: What I was missing was the reference where the semantics are defined (it is not in
perlop
). -
U. Windl almost 3 years@choroba Do you also have an explanation and numbers (Perl version) for it?
-
choroba almost 3 years@U.Windl: It has recently changed, so in the current Perl version(s), %hash in scalar context is equivalent to
keys %hash
. -
U. Windl almost 3 yearsBeing paranoid I used
scalar keys %hash == 0
as test. So!keys ...
is basically doing a test on an array, not on a hash. -
U. Windl almost 3 yearsI agree: While thinking
if (%hash)
might work, I tried to find the specification of the semantics. Probably the confusing part is thatif (@array)
seems to be more clearly defined, but for symmetry it should work for hashes, too. Maybe that is why they changed it recently. -
Schwern almost 3 years@U.Windl Yes,
keys %hash
returns an array.scalar keys %hash
returns an integer. Note that Perl functions are context aware and can optimize.!%hash
is optimized to return a boolean. It does not iterate through its keys, it already has a count. The code is a nightmare, but here's the optimization.i = HvUSEDKEYS(hv);
-
Schwern almost 3 years