1

I am trying to create an array of hashes, and I am wondering how to reference each hash within the array?

For eg:

while(<INFILE>)    
{    
  my $row = $_;    
  chomp $row;    
  my @cols = split(/\t/,$row);    
  my $key = $cols[0]."\t".$cols[1];     

  my @total = (); ## This is my array of hashes - wrong syntax???    

  for($i=2;$i<@cols;$i++)    
  {    
    $total[$c++]{$key} += $cols[$i];      
  }    
}

close INFILE;

foreach (sort keys %total)  #sort keys for one of the hashes within the array - wrong syntax???    
{    
  print $_."\t".$total[0]{$_}."\n";    
}

Thanks in advance for any help.

2
  • The logic in this is a bit more broken than just addressing the use of hashes and arrays. Maybe you could explain what it is you're trying to achieve and we can possibly point you in the right direction. Commented Mar 30, 2011 at 21:34
  • perlmonks.org/?node=References+quick+reference can be very helpful Commented Mar 30, 2011 at 23:05

2 Answers 2

3

You don't need

my @total = ();

This:

my @total;

is sufficient for what you are after. No special syntax needed to declare that your array will contain hashes.

There's probably different ways of doing the foreach part, but this should work:

foreach (sort keys %{$total[$the_index_you_want]}) {
  print $_."\t".$total[$the_index_you_want]{$_}."\n";
}

[BTW, declaring my @total; inside that loop is probably not what you want (it would be reset on each line). Move that outside the first loop.]

And use strict; use warnings;, obviously :-)

Sign up to request clarification or add additional context in comments.

3 Comments

You should always initialize your variables. Although it doesn't do it any more, Apache would restart a mod_perl CGI without resetting the data space to zeros. This meant that whatever values were in there before were re-used. Program defensively: always initialize your variables.
@shawnhcorey: No, program defensively: Use lexical ("my") variables and declare them in the smallest possible scope. If you don't use globals (or lexicals whose scope is the entire program), it doesn't matter whether the data space is zeroed out or not because the variables' values will be lost when they go out of scope.
Sorry, lexical variables are scoped to the block they're in or, if outside of a block, to the file they're in. They cannot be accessed from another file, unlike 'our' variables.
1

Here's what I get:

print join( "\t", @$_{ sort keys %$_ } ), "\n" foreach @total;

I'm simply iterating through @total and for each hashref taking a slice in sorted order and joining those values with tabs.

If you didn't need them in sorted order, you could just

print join( "\t", values %$_ ), "\n" foreach @total;

But I also would compress the line processing like so:

my ( $k1, $k2, @cols ) = split /\t/, $row;
my $key                = "$k1\t$k2";
$totals[ $_ ]{ $key } += $cols[ $_ ] foreach 0..$#cols;

But with List::MoreUtils, you could also do this:

use List::MoreUtils qw<pairwise>;
my ( $k1, $k2, @cols ) = split /\t/, $row;
my $key                = "$k1\t$k2";
pairwise { $a->{ $key } += $b } @totals => @cols;    

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.