Kamilė Vainiūtė
Kamilė Vainiūtė

Reputation: 105

Creating different arrays through loops

Is it possible to create different named arrays while looping in Perl? What I need to do is open some files from @ARGV and put their data in separate arrays in one loop, for example: 1.txt in @first_array, 2.txt in @second_array and etc. Is it possible and if yes, what would be the best approach?

EDIT:

I think I'm getting closer, since Data::Dumper shows a correct structure of what I need, but it doesn't show the values of the files, instead, it shows this:

$VAR1 = {
      'skai.txt' => [
                      \*{'::$fh'},
                      $VAR1->{'skai.txt'}[0],
                      $VAR1->{'skai.txt'}[0],
                      $VAR1->{'skai.txt'}[0]
                    ],
      'numb.txt' => [
                      \*{'::$fh'},
                      $VAR1->{'numb.txt'}[0],
                      $VAR1->{'numb.txt'}[0],
                      $VAR1->{'numb.txt'}[0]
                    ]
    };

Each file consists of 4 numbers. My code looks like this:

use strict;
use warnings;
use Data::Dumper;

my $data = {};

foreach my $arg(@ARGV){
    if(open(my $fh, $arg)){
        $data->{$arg}=[];
        while(<$fh>){
            chomp;
            push @{$data->{$arg}}, $fh;
        }
    close($fh);
    }
}

print Dumper $data;

What is the meaning of \*{'::$fh'}?

Upvotes: 1

Views: 90

Answers (3)

Dave Cross
Dave Cross

Reputation: 69224

This is the strange part of your code:

push @{$data->{$arg}}, $fh;

$fh is the filehandle. That's why you're getting that output. Each time around the loop, you're adding exactly the same value (the filehandle) to your data structure.

'skai.txt' => [
               \*{'::$fh'},
               $VAR1->{'skai.txt'}[0],
               $VAR1->{'skai.txt'}[0],
               $VAR1->{'skai.txt'}[0]
             ],

The first value (\*{'::$fh'}) is just Data::Dumper's slightly over-complicated way of saying "a reference to the filehandle that is stored in $fh". The three subsequent values are Data::Dumper saying "this is a value that already appears in this data structure, so instead of writing the value out again, I'll just show you a reference to the existing value".

I think that if you change that line to:

push @{$data->{$arg}}, $_;

Then you'll get something a lot closer to what you wanted.

Upvotes: 2

Mike Holt
Mike Holt

Reputation: 4602

It sounds like you don't really need the individual arrays to be named @first_array, @second_array, etc. You just want to keep them separate.

In that case, why not just have an array of arrays? Like so:

my @array_of_arrays;

for my $f (@ARGV) {
   my @array = load_file($f);
   push @array_of_arrays, \@array;
}

Note: load_file is just a placeholder for some function you presumably have to read a file into an array.

Then later on...

array_of_arrays[0][0] * array_of_arrays[1][0] * ... * array_of_arrays[$N][0]

Update: You need to pass a reference to @array to the push function, rather than just @array. Otherwise, push will create a flattened array containing all of the elements of each individual array. Thanks to @Garo and @mob for pointing this out.

Upvotes: 2

Garo
Garo

Reputation: 1510

If I understand your question correctly, what you should use is arrayreferences inside a hash, hashref, array or arrayref.

Below is how i would do it (a hashref of arrayrefs):

my $data={};  #a hashref where all data will end up
foreach my $currentfile (@ARGV){
  open (my $filehandle ,$currentfile);
  $data->{$currentfile}=[];  #a empty arrayref inside the hashref for every file
  while(<$fh>) {
    push @{$data->{$currentfile}}; #add lines to the arrayref
  }
  close $filehandle;
}

Result: all data will be available in the form $data->{FILENAME}->[LINENUMBER COUNTING FROM 0].

Example: line 7 of file "foo.txt" will now be in $data->{foo.txt}->[6]

Depending on your actual purpose an array or arrayref might be a better choice then a hashref (If you don't care about the filenames but care about which number of argument they are in @ARGV). But this is not entirely clear in your question

Upvotes: 1

Related Questions