chakri
chakri

Reputation: 31

How to store variable-arrays inside another array?

I have a perl-query on saving arrays inside another array. A related query was asked before(How do I add an array ref to the middle of an existing array in Perl?), but I could not find answer to mine, so I am posting it here.

I have 10 text files, each having approximately 100 lines of text. I want to pick all those lines containing the word "important". Script for doing this operation is below. I save all lines containing word "important" in an array. So, from each text file, I get an array. I want to save all those arrays inside another array ?

my @list_of_files = ("input1.txt", "input2.txt","input3.txt"); my $list_of_files = @list_of_files;

for ($file=0, $file<$list_of_files; $files++){
 open INPUT_FILE, "$list_of_files[$file]" or die "can't open $file : $!";
 my @input = <INPUT_FILE>;
 my $size = @input;

 for ($num=0; $num<$size; $num++){
  if ($input[$num] =~ m/important/) {
   push (@sub_array, $output);
  }
 }
 close INPUT_FILE;
 push (@main_array, \@sub_array);   
}

elements of @sub_array changes every time, so, how do I preserve elements of all sub_arrays ? I would like to have final output as @main_array, which contains 3 elements, each element is an array of elements (lines containing the word "important")

Any help is much appreciated TIA

Upvotes: 3

Views: 2329

Answers (3)

bvr
bvr

Reputation: 9697

I would solve your problem like this:

my @list_of_files = ("input1.txt", "input2.txt", "input3.txt");

my @lines_in_file = ();                 # target array
for my $file (@list_of_files) {
    open(my $in,'<',$file) or die "can't open $file : $!";

    my $lines = [];                     # scalar containing arrayref for important lines
    while(my $input = <$in>) {
        if($input =~ /important/) {
            push @$lines, $input;       # push into arrayref
        }
    }
    close $in;

    push @lines_in_file, $lines;        # push arrayref into main array
}

Few things to note:

  • perl for can traverse array without hassle of C-style for
  • it is better to process file line-by-line, instead of reading whole thing into memory, especially for line based processing
  • [] construct new arrayref in each iteration. If you reuse @sub_array in each loop and take reference of it, you end up with many references to same thing

Upvotes: 4

Roman Grazhdan
Roman Grazhdan

Reputation: 477

If you are going to write something in Perl now and then, you will have to understand how references work and how to build complex data structures.

Being a Perl newbie myself, I would recommend you to visit perldoc.perl.org, the manuals section, and work through first three lessons. It would only take you about an hour and a half and you will have an idea on how to solve your problem and others of that kind.

The tutorials are really helpful - brief and practical. You will learn to pass data structures around and iterate on them and whatnot.

For testing, consider using Data::Dumper and print Dumper($var) to look inside your complicated data structures easily.

Upvotes: 3

Dave Cross
Dave Cross

Reputation: 69314

I would do it slightly differently to bvr. But his points still stand.

# use qw() to define line with less punctuation
my @list_of_files = qw(input1.txt input2.txt input3.txt);

my @lines_in_file;

foreach my $file (@list_of_files) {
  open(my $in, '<', $file) or die "can't open $file : $!";

  # declare an array, not a scalar
  my @lines;

  # idiomatic use of while(<>) puts each record into $_
  while (<$in>) {
    # /../ works on $_ by default.
    # Postfix condition is more readable
    push @lines, $_ if /important/;
  }

  # Take reference to array and push it onto main array
  push @lines_in_file, \@lines;
}

Upvotes: 5

Related Questions