Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

Counting hash of hashes elements

by albert (Monk)
on Nov 01, 2004 at 11:15 UTC ( [id://404271]=perlquestion: print w/replies, xml ) Need Help??

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

I'd like to count keys in a hash of hashes based on their values. I have an example hash snipit as follows:
%hash = ( 'a' => { 'x' => 40, 'z' => 102 }, 'b' => { 'z' => 100, 'x' => 10, 'y' => 20 }, 'c' => { 'x' => 50 }, 'd' => { 'z' => 101, 'y' => 30 } );
There are a couple of different ways I'd like to count the keys on this hash.

1. How can I count the number of keys where 'x' has a defined value, but does not have a value for 'y'?

2. How can I count the number of keys which have a defined value for 'z'?

Thanks for all shared wisdom.

Update:

Thanks for showing me how to do this.

One additional thing I forgot to ask in my original question.

How would I also count the number of keys with a value of 101 for 'z'?

Replies are listed 'Best First'.
Re: Counting hash of hashes elements
by edan (Curate) on Nov 01, 2004 at 11:25 UTC
    my $defined_x_no_y = grep { defined $_->{x} && !defined $_->{y} } valu +es %hash; my $defined_z = grep { defined $_->{z} } values %hash;

    Note that I used defined and not exists, since you said "defined", but you might have meant "exists" ...

    --
    edan

Re: Counting hash of hashes elements
by Aragorn (Curate) on Nov 01, 2004 at 11:25 UTC
    Here's a way:
    #!/usr/local/bin/perl use strict; use warnings; my %hash = ( 'a' => { 'x' => 40, 'z' => 102 }, 'b' => { 'z' => 100, 'x' => 10, 'y' => 20 }, 'c' => { 'x' => 50 }, 'd' => { 'z' => 101, 'y' => 30 } ); my $x_but_not_y = 0; my $z = 0; foreach my $key (keys %hash) { $x_but_not_y++ if defined $hash{$key}->{x} and not defined $hash{$ +key}->{y}; $z++ if defined $hash{$key}->{z}; } print "number of keys where x defined, but not y: $x_but_not_y\n"; print "number of keys where z defined: $z\n";
    Arjen
Re: Counting hash of hashes elements
by perlcapt (Pilgrim) on Nov 01, 2004 at 11:53 UTC
    Hashes are great for statistics. In the following method, I use a string composed of the variety of keys to index the statistics:
    #!/usr/bin/perl -w use strict; my %hash = ( 'a' => { 'x' => 40, 'z' => 102 }, 'b' => { 'z' => 100, 'x' => 10, 'y' => 20 }, 'c' => { 'x' => 50 }, 'd' => { 'z' => 101, 'y' => 30 } ); sub stats { my %hhp = @_; my %counters; # a counter hash of which keys are used at level two foreach my $key1 (keys %hhp) { my @cList = (); foreach my $key2 (keys %{$hhp{$key1}}) { push(@cList,$key2); } ++$counters{join('+',sort @cList)}; } return %counters; } #### main my %result = stats(%hash); foreach my $key (keys %result){ print "$key $result{$key}\n"; }
    The result looks like this:
    x+y+z 1 y+z 1 x+z 1 x 1
    To do statistics on the actual values.. use the same logic.
    perlcapt
    -ben
Re: Counting hash of hashes elements
by NetWallah (Canon) on Nov 01, 2004 at 17:07 UTC
    Here is a performance-improved version of perlcapt's solution - this one includes a response to your last query.
    #!/usr/bin/perl -w use strict; use warnings; my %hash = ( 'a' => { 'x' => 40, 'z' => 102 }, 'b' => { 'z' => 100, 'x' => 10, 'y' => 20 }, 'c' => { 'x' => 50 }, 'd' => { 'z' => 101, 'y' => 30 } ); sub stats { my ($hhp, $SearchKey, $SearchVal) = @_; my %counters; # a counter hash of which keys are used at level two my $SearchCount; foreach my $key1 (keys %$hhp) { my @cList = keys %{$hhp->{$key1}}; ++$counters{join('+',sort @cList)}; ++$SearchCount if exists $hhp->{$key1}->{$SearchKey} and $hhp->{$key1}->{$SearchKey} == $SearchVal +; } return $SearchCount, %counters; } #### main my ($SearchCount, %result) = stats(\%hash,'z',101); foreach my $key (sort keys %result){ print "$key \t$result{$key}\n"; } print "Count of z==101 is $SearchCount\n"; __END__ ## OUTPUT ## x 1 x+y+z 1 x+z 1 y+z 1 Count of z==101 is 1

        Earth first! (We'll rob the other planets later)

      The direct generation of the $key2 list directly into @cList is a nice improvement. I just want to add one more version more in the spirit of general statistical collection rather than situation testing. In this version, you can see what I call structural flattening. (Not sure that is the most appropriate term for it, but hey, I'm JAPH.)

      If the statistics are too detailed or at the wrong level, just modify the sprintf expression.

      We have pretty much hammered this little problem to death.

      sub stats { my %hhp = @_; my $keyCounter = {}; # a counter hash of which keys are used at le +vel two my $statCounter = {}; # a counter for the actual values foreach my $key1 (keys %hhp) { my @cList = (); foreach my $key2 (sort keys %{$hhp{$key1}}) { push(@cList,$key2); my $statKey = sprintf("%s->%s=%s",$key1,$key2,$hhp{$key1}{$ +key2}); ++ $$statCounter{$statKey}; # make statistical entry on val +ue } ++ $$keyCounter{join('+',@cList)}; # make statistical entry on + key2 } return ($keyCounter,$statCounter); } #### main my ($keyResult,$statResult) = stats(%hash); foreach my $hash ($keyResult,$statResult){ foreach my $key (sort keys %$hash){ print "$key $$hash{$key}\n"; } } __END__ ## the result x 1 x+y+z 1 x+z 1 y+z 1 a->x=40 1 a->z=102 1 b->x=10 1 b->y=20 1 b->z=100 1 c->x=50 1 d->y=30 1 d->z=101 1
      perlcapt
      -ben
Re: Counting hash of hashes elements
by TedPride (Priest) on Nov 01, 2004 at 20:59 UTC
    It looks to me like you don't care if the key is defined, what you're interested in is if there's a value. So I'm not bothering with defined or exists here:
    $c = 0; for (keys %hash) { $c++ if $hash{$_}{'x'} && !$hash{$_}{'y'}; +} print "$c\n"; $c = 0; for (keys %hash) { $c++ if $hash{$_}{'z'}; } print "$c\n"; $c = 0; for (keys %hash) { $c++ if $hash{$_}{'z'} == 101; } print "$c\ +n";

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://404271]
Approved by Arunbear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (2)
As of 2024-04-26 03:51 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found