Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

How would i go about getting the number of keys of the hash that's within my hash?

For example, if i had a main hash which contained hashes named first, second, third. How could i find out how many keys that the hash first contained?

I've been trying to simply use the hash in a scalar context but i must be referencing something wrong because everything i try gives some kind of syntax error.

Replies are listed 'Best First'.
Re: num keys of the hash within hash?
by FunkyMonk (Bishop) on May 26, 2009 at 15:59 UTC
    Use keys in scalar context. ie
    my $count = keys %hash;

    or

    my $count = keys %{$hash{first}};

    if you've got a hash of hashes

Re: num keys of the hash within hash?
by DStaal (Chaplain) on May 26, 2009 at 15:55 UTC

    What have you tried? That's really the best way to do these.

    I think something along the lines of scalar @{hash{first}} should work, although I haven't tried it at the moment.

Re: num keys of the hash within hash?
by kennethk (Abbot) on May 26, 2009 at 15:59 UTC
    There are two possibilities here, and without seeing your code I can only guess.

    Using a hash in scalar context returns "x/y", where x is the number of values and y is the number of allocated buckets (see Scalar values). If you have warnings on, using that in numeric context will warn you that something that wasn't a number was used as one. Of course, since the leading number is exactly what you want, the numification is actually successful even though the interpreter spits a warning. You can fix this by using keys or values in scalar context instead or suppressing the warning locally.

    The other possibility is that you are passing a reference when you intend to be passing a hash (a hash or hashes is really a hash of hash references). See perlref and/or perlreftut for information on dereferencing.

      ... since the leading number is exactly what you want, the numification is actually successful ...
      However, the leading number may not be quite what is wanted.

      Consider the following example:

      >perl -wMstrict -le "my %hash = ( one => { fee => 33, fie => 44, }, two => { foo => 2, bar => 3, baz => 4, }, ); my $k_n = keys %{ $hash{one} }; my $k_s = '' . %{ $hash{one} }; print $k_n; print $k_s, ' <--'; print scalar keys %{ $hash{two} }; print '' . %{ $hash{two} }; " 2 1/8 <-- 3 3/8 >perl -wMstrict -le "my %hash = ( one => { fee => 33, xyz => 44, }, two => { foo => 2, bar => 3, baz => 4, }, ); my $k_n = keys %{ $hash{one} }; my $k_s = '' . %{ $hash{one} }; print $k_n; print $k_s, ' <--'; print scalar keys %{ $hash{two} }; print '' . %{ $hash{two} }; " 2 2/8 <-- 3 3/8
      In the both cases, the evaluation of  scalar keys %{ $hash{one} } (or of  keys %{ $hash{one} in a scalar context) is (and always will be) the same: 2.

      However, the first digit of the stringization of  '' . %{ $hash{one} } is not the same in both cases. There has been an unfortunate collision in  one => { fee => 33, fie => 44 } and both 'fee' and 'fie' occupy the same bucket of the 8 allocated for this (anonymous) (sub-)hash. With  one => { fee => 33, xyz => 44 }, this tragedy has been avoided and the two keys occupy two separate buckets.

      Moral: As recommended by kennethk, always use the scalar evaluation of keys, not the stringization of the hash which, while interesting, may be misleading. And please don't suppress warnings without good reason.

      Update: Here's a much more concise example. The details of the discussion above don't quite apply any more, but you get the picture.

      >perl -wMstrict -le "my %ha = ( fee => 33, fie => 44, ); my %hb = ( fee => 33, xyz => 44, ); printf qq{keys (%s): %ld %s \n}, join(' ', sort keys %$_), scalar keys %$_, 'buckets used/allocated: ' . %$_, for \(%ha, %hb); " keys (fee fie): 2 buckets used/allocated: 1/8 keys (fee xyz): 2 buckets used/allocated: 2/8
Re: num keys of the hash within hash?
by muzakfetch (Scribe) on May 26, 2009 at 17:09 UTC
    Maybe this is what you're looking for:
    #!/usr/bin/perl use warnings; use strict; my $hashref = { first => { foo => bar, bar => baz, flop => floodle }, second => { bar => foo, baz => bar, etc => plodle } }; foreach ( keys %{$hashref} ) { print $_ . " contains " . scalar(%{$hashref->{$_}) . " keys.\n"; }
    keys returns a scalar of keys, which you can count with scalar. :-) edit: put a pretty space before keys :-)
      >perl -wMstrict -le "my $hashref = { first => { foo => 'bar', bar => 'baz', flop => 'floodle' }, second => { bar => 'foo', baz => 'bar', etc => 'plodle' }, }; foreach ( keys %{$hashref} ) { print qq{$_ contains } . scalar(%{$hashref->{$_}}) . qq{ keys.}; } " first contains 3/8 keys. second contains 3/8 keys.
      Please note:
      • proper string definitions of values of hashes;
      •  scalar(%{$hashref->{$_}}) vice  scalar(%{$hashref->{$_});
      • per Re^2: num keys of the hash within hash?, the stringization of a hash does not necessarily imply the number of keys of the hash.
Re: num keys of the hash within hash?
by FunkyMonk (Bishop) on May 26, 2009 at 15:56 UTC
    Double post. See below...

    Use keys in scalar context. ie

    my $count = keys %hash;