Sam Weisenthal
Sam Weisenthal

Reputation: 2951

Printing in unexpected order

I expected the following to print in the order of the elements of @Data, but it's printing in the order of the elements of @Queries. Am I missing something? I also tried declaring the items to be printed after foreach(@data){... and then printing inside that loop, but still wrong order.

$datafile is a file with the following:

GR29929,JAMES^BOB
GR21122,HANK^REN

$queryfile is a file with the following:

(3123123212):# FD  [GR21122]
line 2
line 3
line 4
(12): # FD         [HANK^REN]
line 6
line 7
line 8
(13): # FD           [Y]
-------------------------------
--------------------------------
(3123123212):# FD  [GR29929]
line 2
line 3
line 4
(12): #  FD       [JAMES^BOB]
line 6
line 7
line 8
(13): # FD           [Z]

The output file is:

GR21122,HANK^WREN,Y
GR29929,JAMES^BOB,Z

When I want:

GR29929,JAMES^BOB,Z    
GR21122,HANK^WREN,Y

Code is:

open(DA, "<$datafile");
open(QR, "<$queryfile");
my @Data = <DA>;
my @Queries = <QR>;
foreach (@Data) {
    my ( $acce, $namee ) = split( ',', $_ );
    chomp $acce;
    chomp $namee;
    print "'$acce' and '$namee'\n";

    for my $i ( 0 .. $#Queries ) {
        my $Qacce = $Queries[$i];
        my $Qname = $Queries[ $i + 4 ];
        my $Gen   = $Queries[ $i + 8 ];

        if ( $Qacce =~ m/$acce/ and $Qname =~ m/$namee/ ) {
            my ($acc) = $Qacce =~ /\[(.+?)\]/;
            my ($gen) = $Gen =~ /\[(.+?)\]/;
            $gen =~ s/\s+$//;
            my ($name) = $Qname =~ /\[(.+?)\]/;

            print GL "$i,$acc,$gen,$name\n";
        }
    }
}

Upvotes: 1

Views: 83

Answers (1)

Borodin
Borodin

Reputation: 126742

The basic shell of your program prints what you ask for, but there is a lot missing. The refactoring below should do what you want.

You had a problem with the values of your $i index variable, so that the first time around the loop you were accessing @data elements [0, 4, 8], the second time [1, 5, 9] etc. It looks like the second loop execution should use elements [11, 15, 19] and so on. Please correct me if I'm wrong.

In addition you were using regular expressions to compare the keys in the two files, and you were finding nothing because the name values contain caret ^ characters which are special within regexes. Escaping the strings using \Q...\E fixed this.

Note that a better solution would use hashes to match keys across the two files, but without details on your file format - particularly queryfile - I have had to follow your own algorithm.

use strict;
use warnings;
use autodie;

my ($data_file, $query_file) = qw/ datafile.txt queryfile.txt /;

my @queries = do {
  open my $query_fh, '<', $query_file;
  <$query_fh>;
};
chomp @queries;

open my $data_fh,  '<', $data_file;

while (<$data_fh>) {
  chomp;
  my ($acce, $namee) = split /,/;

  for (my $i = 0; $i < @queries; $i += 11) {
    my ($qacce, $qname, $qgen) = @queries[$i, $i+4, $i+8];

    if ( $qacce =~ /\Q$acce\E/ and $qname =~ /\Q$namee\E/ ) {
      my ($acc, $name, $gen) = map / \[ ( [^\[\]]+ ) \] /x, ($qacce, $qname, $qgen);
      $gen =~ s/\s+\z//;

      print "$acc,$name,$gen\n";
    }
  }
}

output

GR29929,JAMES^BOB,Z
GR21122,HANK^REN,Y

Upvotes: 1

Related Questions