tags:

views:

71

answers:

1

i have a problem where I need to have an array as a value in an associative array.

Go through the code below. Here I am trying to loop the files in a directory and it is more likely that more than 1 file can have the same ctrno. So, I would like to see what are all the files having the same ctrno. The code below gives error at "$ctrno_hash[$ctrno] = @arr;" in the else condition. The same case would be for if condition as well.

Am I following the right approach or could it be done differently?

sub loop_through_files
{
    $file = "@_";
    open(INPFILE, "$file") or die $!;
    #print "$file:$ctrno\n";
    while (<INPFILE>)
    {
       $line .= $_;
    }
    if ($line =~ /$ctrno/ )
    {
       print "found\n";
       if ( exists $ctrno_hash[$ctrno])
       {
          local @arr = $ctrno_hash[$ctrno];
          push (@arr, $file);
          $ctrno_hash[$ctrno] =  @arr;
       }
       else
       {
          local @arr;
          push(@arr, $file);
          $ctrno_hash[$ctrno] =  @arr;
       }
    }
}
+3  A: 

I believe you want something like

$ctrno_hash[$ctrno] =  \@arr;

This will turn the array @arr into a array reference.

You then refer to the previously pushed array reference with

@{$ctrno_hash[$ctrno]}

That is, if $array_ref is an array reference, the construct @{ $array_ref } returns the array to which the array reference points.

Now, the construct $ctrno_hash[$ctrno] is not really a hash, but an ordinary array. In order to truly make it a hash, you need the curly brackets instead of the square brackets:

@{$ctrno_hash{$ctrno} } = \@arr;

And similarly, you later refer to the array with

@{$ctrno_hash{$ctrno} }

Now, having said that, you can entirly forgo the if ... exists construct:

if ($line =~ /$ctrno/ )
{
   print "found\n";
   push @{$ctrno_hash{$ctrno}}, $file
}
René Nyffenegger
Thank you. It worked.
Jagannath