perlwhile-loop

Perl: Pulling pairs of values from an array


Consider

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

while(<DATA>) {
  my($t1,$t2,$value);
  ($t1,$t2)=qw(A P); $value = $1 if /^$t1.*$t2=(.)/;
  ($t1,$t2)=qw(B Q); $value = $1 if /^$t1.*$t2=(.)/;
  ($t1,$t2)=qw(C R); $value = $1 if /^$t1.*$t2=(.)/;
  print "$value\n";
}

__DATA__
A P=1 Q=2 R=3
B P=8 Q=2 R=7
C Q=2 P=1 R=3

I'd like to replace the repetition with an elegant loop over pairs of $t1,$t2 values stored in an array (or other structure) like one of

my @pairs = qw (A,P   B,Q   C,R);
my @pairs = qw (A P   B Q   C R);

I've not had much success with a brief attempt at combining while, split and unshift.

What concise, elegant solution am I missing?


P.S. I've used hashes in the past but find the %h = (A=>'P', B=>'Q', C=>'R') syntax "noisy". It's also ugly to extend to triplets, quads ...


Solution

  • When a hash + each isn't good enough (because

    there is the List::MoreUtils::natatime method:

    use List::MoreUtils q/natatime/;
    
    while(<DATA>) {
      my($t1,$t2,$value);
      my @pairs = qw(A P B Q C R);
      my $it = natatime 2, @pairs;
      while (($t1,$t2) = $it->()) {
          $value = $1 if /^$t1.*$t2=(.)/;
      }
      print "$value\n";
    }
    
    __DATA__
    A P=1 Q=2 R=3
    B P=8 Q=2 R=7
    C Q=2 P=1 R=3
    

    Usually, though, I'll just splice out the first few elements of the list for a task like this:

    while(<DATA>) {
      my($t1,$t2,$value);
      my @pairs = qw(A P B Q C R);
      # could also say  @pairs = (A => P, B => Q, C => R);
      while (@pairs) {
          ($t1,$t2) = splice @pairs, 0, 2;
          $value = $1 if /^$t1.*$t2=(.)/;
      }
      print "$value\n";
    }