Bruc Walker
Bruc Walker

Reputation: 253

what's the best way to get multiple values from a perl array?

For example,

First, I get the dataRecord into an array like this,

  my @dataRecord = split(/\n/);

Next, I filter on the array data record to get the test lines like this,

  @dataRecord = grep(/test_names/,@dataRecord);

Next, I need to get the test names from the test line like this,

   my ($test1_name,$test2_name,$test3_name)  = getTestName(@dataRecord);

   sub getTestName
   {
       my $str = shift @_;
       # testing the str for data and 
       print str,"\n"; # This test point works in that I see the whole test line.
       $str =~ m{/^test1 (.*), test2 (.*), test3 (.)/};
       print $1, "\n"; # This test point does not work. 
       return ($1,$2,$3);
    }

Is there a better way for me to acommplish this task?

Upvotes: 1

Views: 3276

Answers (2)

Eric Strom
Eric Strom

Reputation: 40142

You can chain operations together while reducing the syntax required. This has the advantage of emphasizing the important parts of the program while reducing the syntax noise.

my @test = map m{/^test1 (.*), test2 (.*), test3 (.)/},
           grep /test_names/,
           split /\n/;

# use $test[0], $test[1], $test[2] here

If you are trying to debug a problem, map and grep can take blocks, making it easy to insert error checking code:

my @test = map {
               if (my @match = m{/^test1 (.*), test2 (.*), test3 (.)/}) {
                   @match
               } else {
                   die "regex did not match for: $_"
               }
           } # no comma here
           grep /test_names/,
           split /\n/;

Here are a few different ways to assign from an array that aren't directly related to your question, but are probably useful:

my ($zero, $one,  $two) = @array;
my (undef, $one,  $two) = @array;
my (undef, undef, $two) = @array;  # better written `my $two = $array[2];`

my ($one, $two) = @array[1, 2];    # note that 'array' is prefixed with a @
my ($one, $two) = @array[1 .. 2];  # indicating that you are requesting a list
                                   # in turn, the [subscript] sees list context
my @slice = @array[$start .. $stop];  # which lets you select ranges

To unpack the args to a subroutine:

my ($first, $second, @rest) = @_;

In a method that takes name => value pairs:

my ($self, %pairs) = @_;

Upvotes: 4

Michał Wojciechowski
Michał Wojciechowski

Reputation: 2490

You can get a list of matching subexpressions by using the m// operator in list context, for example by assigning its return value to a list of variables (like you currently do with the subroutine call). So, you can replace the subroutine with a much simpler construct:

my $str = shift @dataRecord;
my ($test1_name, $test2_name, $test3_name) =
    $str =~ m/^test1 (.*), test2 (.*), test3 (.)/;

Or, a for loop if you want to do this for each element of the @dataRecord array:

for my $str (@dataRecord) {
    my ($test1_name, $test2_name, $test3_name) =
        $str =~ m/^test1 (.*), test2 (.*), test3 (.)/;
}

Upvotes: 0

Related Questions