Perl: Getting number of keys in a hash

A friend queried:

I’ve got a hash array and I want to determine the number of keys in the array. what’s the best way to do so?

This is an interesting question. I can think of a one definite way to do it:

@z = keys %foo ; $nkeys = $#z + 1 ;

…but none of the various apparently-perl-orthogonal ways to get this data seemed to work.

I tried $#foo, which just yielded -1; then I tried scalar %foo which yielded something odd, and (worse) nondeterministic:

$ cat z
$f{“1”} = 1;
$f{“2”} = 1;
$f{“3”} = 1;
$f{“4”} = 1;
$f{“5”} = 1;
$f{“6”} = 1;
$f{“7”} = 1;
print scalar(%f), “\n”;
$ perl z
5/8
$ perl z
6/8
$ perl z
4/8

…which I suspect reflects some hashing statistics. So, either we’d need to use the “keys” trick above, or something like

@z = %foo ; $nkeys = ($#z+1)/2 ;

Does anyone know a faster way?

Comments

4 responses to “Perl: Getting number of keys in a hash”

  1. Elfie
    re: Perl: Getting number of keys in a hash

    In a scalar context, the keys function gives the number of elements (key-value pairs) in the hash. For example, you can find out whether a hash is empty:

    if (keys(%somehash)) { # if keys() not zero: …; # array is non empty } # … or … while (keys(%somehash) < 10) { …; # keep looping while we have fewer than 10 elements }

  2. Alan Burlison
    re: Perl: Getting number of keys in a hash

    Elfie is right, scalar(keys(%foo)) is the way to do it. Evaluating a hash in a scalar context gives the number of used and allocated buckets in the hash. The reason your test program is nodeterministic is because you are using a recent version of perl that has deliberately added a random component to hash key caclulation to prevent DOS attacks on CGI scripts – see http search.cpan.org/dist/perl/pod/perlsec.pod#Algorithmic_Complexity_Attacks and http http://www.cs.rice.edu/~scrosby/hash/ .

    $#foo is an attempt to find the last index of the non-existent @foo array, hence the -1 value.

  3. Tim Bray
    re: Perl: Getting number of keys in a hash

    $numKeys = keys(%foo);

  4. alecm
    re: Perl: Getting number of keys in a hash

    …thereby implicitly casting keys into a scalar context. cool.

Leave a Reply

Your email address will not be published. Required fields are marked *