0

i'm trying the get specific elements from array in perl but the code is not working

print "Enter the column numbers you want separated by comma "; 
$temp=<>; 

@shortdays = qw/Mon Tue Wed Thu Fri Sat Sun/; 
@weekdays = @shortdays[scalar $temp];  

print @weekdays;
Guru
  • 16,456
  • 2
  • 33
  • 46
user2235827
  • 9
  • 1
  • 3

5 Answers5

2

If you want to take a slice of the array, you must put a list of numbers inside the brackets [ .. ], not a string. One string is a list of one, of course, and it will get treated as a number and therefore converted to a number, but as you noted, it will only be the first number.

If you had use warnings turned on, which I strongly suspect you do not, you would get the error:

Argument "3,4\n" isn't numeric in array slice at yourscript.pl ...

But Perl does convert this string to a number as best it can, and comes up with 3.

So, that's what you did wrong. What you could do instead:

my @nums = $temp =~ /\d+/g;
my @weekdays = @shortdays[@nums];  

Which would extract the integers from the string in a reasonably simple manner. It would also remove the requirement of using a specific delimiter such as comma. Note that capturing parentheses are implied when using the global /g modifier.

If you're absolutely set on using commas, use split to extract the numbers. But be aware that this may leave whitespace and other unwanted characters.

my @nums = split /,/, $temp;

While debugging, using a statement such as

print @weekdays;

Is a bit confusing. I would recommend that you instead do this:

use Data::Dumper;

...

print Dumper \@weekdays;

Then you will see exactly what the array contains.

And of course, add these two lines to all your scripts:

use strict;
use warnings;

If you had used these, you would not be having this problem. The information and control and reduced debugging time that these two pragmas provide more than make up for the short learning curve associated with using them.

TLP
  • 66,756
  • 10
  • 92
  • 149
0

This works at my place:

my $temp=<>;
my @shortdays = qw/Mon Tue Wed Thu Fri Sat Sun/;
my @id=split ",",$temp;
my @weekdays;

for(@id)
{
push(@weekdays,@shortdays[$_]);
}
print @weekdays;
Vijay
  • 65,327
  • 90
  • 227
  • 319
  • Why did you use a [`for` loop](http://perldoc.perl.org/perlsyn.html#For-Loops)? Just use a list slice `@weekdays = @shortdays[@id];` – Brad Gilbert Apr 02 '13 at 17:10
0

Do it like this:

#!/usr/bin/perl -w
use strict;

print "Enter the column numbers you want separated by comma ";     
my $temp=<>;
my @a1=split(/,/,$temp);
my @shortdays = qw/Mon Tue Wed Thu Fri Sat Sun/;
my @weekdays = @shortdays[@a1];
print "@weekdays";
Guru
  • 16,456
  • 2
  • 33
  • 46
  • You shouldn't specify [`warnings`](http://perldoc.perl.org/warnings.html) by using [`-w`](http://perldoc.perl.org/perlrun.html#*-w*) on the shebang line. – Brad Gilbert Apr 02 '13 at 17:42
  • @BradGilbert : Brad, any specific reason why -w is not preferred? – Guru Apr 03 '13 at 01:23
  • 1
    For one thing, it only works if the file is the one specified on the command line. It never works for modules, neither Perl5 (`.pm`) nor Perl4 (`.pl`) style modules. It is possible to call a script like this `perl -e'use diagnostics; do("script.pl")'`, in that case [`-w`](http://perldoc.perl.org/perlrun.html#%2A-w%2A "perldoc perlrun") is never applied. (of course in that case it would be better written as `perl -Mdiagnostics script.pl`) – Brad Gilbert Apr 03 '13 at 13:49
0

One way to achieve what you want using your approach would be

@weekdays = @shortdays[split(","$temp)]; 

And the print looks better this way:

print join(' ',@weekdays), "\n";
mplwork
  • 1,120
  • 10
  • 21
0
use strict;
use warnings;

my @shortdays = qw'Mon Tue Wed Thu Fri Sat Sun';

print "Enter the column numbers you want\n";

my $line = <STDIN>;
my @ids = $line =~ /[0-7]/g;
my @days = @shortdays[ @ids ];

print join( ', ', @days ), "\n";

Since you only need $line, and @ids once, you can get away without using them.

# my $line = <STDIN>;
# my @ids = $line =~ /[0-7]/g;
# my @days = @shortdays[ @ids ];
my @days = @shortdays[ <STDIN> =~ /[0-7]/g ];

Why /[0-7]/g you might ask.

  • The only valid numbers are 0..7.
  • Don't need to know what the user uses to separate the numbers.
  • /g will give us a list of matches.

Since the regex only matches a single digit, we don't need to specify what the user should use to separate the numbers. Actually, (in this case) the user doesn't even need to separate them at all.

Brad Gilbert
  • 33,846
  • 11
  • 78
  • 129