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

I have the following hash: BodyTemp{$person_num}{$date} which has already been populated.

Suppose I want to find the number of values falling above a certain level for each person, and assign it to a hash of its own. I'd like to use Grep, but there's apparently a syntax problem:

my @personlist=("1"..."1000") my ($person,%high_temp_days); foreach $person (@personlist) { %high_temp_days{$person}=grep {$_>300} values %BodyTemp{$person}; #the above two lines are one line }
Can someone help me fix this? Thanks a million!

Replies are listed 'Best First'.
Re: How to extract a row or column of two-dimensional hash
by toolic (Bishop) on Jan 11, 2008 at 20:32 UTC
    Welcome to the Monastery.

    It is difficult to read your code without code tags. See Writeup Formatting Tips.

    The code you provided does not compile due to a few syntax errors:

    • Missing semicolon after the 1st my statement.
    • Do not use the % sigil to assign values to a hash; use the $ sigil. For example: $high_temp_days{$person} =

    Is it possible for you to show a little of the structure and contents of BodyTemp? You could do this with:

    use Data::Dumper; print Dumper(\%BodyTemp);

    You may also find HASHES OF HASHES helpful in figuring out how to access this type of data structure.

    Also, it is a good practice to use the strictures:

    use warnings; use strict;
      Toolic, I had already read the link you provided (and I am using #strict in my code), but didn't find what I needed. Let me try to ask again, using the examples provided in the link (with a few values changes). Please understand also that I've consulted about six Perl books (3 Llama ones) in search of the answer, so I've spent a fair bit of time on this.) I want to count the number of members of each family named jane. I tried the following code:
      #to make this easier to read, HoH is defined below.
      my ($group);
      for $group ("simpsons","jetsons" ) {
      my $janemembers=grep {$_ eq "jane"} values $HoH{$group};
      }
      The error given is that "Type of arg1 to values must be hash (not hash element). What's going wrong??
      %HoH = (
      flintstones => {
      lead => "fred",
      pal => "barney",
      },
      jetsons => {
      lead => "george",
      wife => "jane",
      kid => "jane",
      },
      simpsons => {
      lead => "homer",
      wife => "marge",
      kid => "bart",
      },
      );
        The error message "Type of arg1 to values must be hash (not hash element)" is giving you precisely the fix you need.

        $HoH{$group} is a hash element. The keys function you have in front of it wants a hash, not a hash element. Since that hash element is a reference to the actual hash, you must dereference the reference to get to the hash. In this case, wrap %{ ... } around it, as in %{$HoH{$group}}, and put keys in front of that.

        I'm surprised you checked "3 llamas". The llama doesn't talk about references (deliberately, because there's only so much we can cover in a week). You want The Alpaca instead, which covers this topic (and more!).

        When posting code, please use "code" tags, not "br" tags, as described in Writeup Formatting Tips.

        Updated: $HoH{$group} is a reference to a hash. I refactored your code as follows:

        #!/usr/bin/env perl use warnings; use strict; my %HoH = ( flintstones => { lead => "fred", pal => "barney", }, jetsons => { lead => "george", wife => "jane", kid => "jane", }, simpsons => { lead => "homer", wife => "marge", kid => "bart", }, ); my $total_jane_count = 0; for my $group ("simpsons" ,"jetsons" ) { my %family_hash = %{ $HoH{$group} }; for my $name (values %family_hash) { if ($name eq 'jane') { $total_jane_count++ } } } print "total_jane_count = $total_jane_count\n";

        This prints:

        total_jane_count = 2
Re: How to extract a row or column of two-dimensional hash
by locked_user sundialsvc4 (Abbot) on Jan 11, 2008 at 20:16 UTC

    Don't try to “bum code” too much: there is no return-on-investment in that. The basic structure of this routine is going to be to loop through each person-ID, then inner-loop through each person's values, and within that nested loop test the value and use the key to populate a separate hash. It's going to be a dozen source-lines at most. So, just find a correct way to do it and don't worry about it being an elegant way to do it. “Correct” is always “elegant.”

      Thank you for the quick response. I know that I can use a foreach loop, and that's how I've been doing it so far. But, for future reference, if I want to refer to a row of a hash in grep, how would I do it? Or alternatively, what would be the syntax for assigning the row of the two dimensional hash to a new variable (itself a one dimensional hash).