Anoop Sethu
Anoop Sethu

Reputation: 47

Print array elements dynamically using range

I have the following code:

  #!/usr/bin/perl

open (FH, "input.txt") or die $!;

my @contents = <FH>;
my $count = 0;

map
{
   $count ++;
   if($_ =~ /This/)
   {
       print "\nNext 3 lines:\n$contents[$count+1] $contents[$count+2] $contents[$count+3]";
   }
} @contents;

Summary of program: 1. Get an input file. 2. If the line contains 'This', then print the next 3 lines.

I was wondering how can I modify the print statement to show the array contents using range. That is, something like below:

print "\nNext 3 lines:\n$contents[$count..$count+3]";

Can anyone point out what is the right way to achieve this?

PS: My problem here is in showing array range. Please don't discuss the efficiency of the program.

Upvotes: 1

Views: 528

Answers (2)

Dave Cross
Dave Cross

Reputation: 69244

The syntax that you want is

@contents[$count..$count+3]

It's called an array slice.

But you probably want something like:

@contents[$count..min($count+3, $#count)]

to avoid falling off the end of the array.

And please don't use map in void context like that. If you're not using the return value from map then foreach (or for) is far less confusing for the people who need to maintain your code later (even if that's you in two weeks time).

Update: In the comments, @DaveVogt just pointed out that your count starts from 1 rather that the more common 0. The easiest way to get round that is probably to move the $count++ to the end of the loop body.

So here's how I'd write it (well, it's probably not how I'd write it at all - but it's how I'd write it starting from your version).

#!/usr/bin/perl

use strict;
use warnings;
use List::Util 'min';

open my $in_fh, 'input.txt' or die $!;

my @contents = <$in_fh>;
my $count = 0;

foreach (@contents) {
  if (/This/) {
    next if $count >= $#contents;
    my $end = min($count+3, $#contents);
    print "\nNext three lines: @contents[$count+1..$end]";
  }
  $count++;
}

Upvotes: 3

fugu
fugu

Reputation: 6578

#!/usr/bin/perl
use warnings;
use strict;

my @lines = ('one', 'two', 'This line', 'That line', 'Other line', 'Last line', 'three', 'four');

my $count = 0;

foreach(@lines){
    $count = 4 if /This/;
    print "$_\n" if ($count-- > 0);
}

On reading through your array this will set $count to 4 on encountering a This, and will print the line until $count -1 is > 0 (i.e. the first incidence prints the line itself, and then the next 3 lines)

Upvotes: 3

Related Questions