in reply to help with loop

Another approach would be to use the hash both as a lookup table to filter on relevant entries (as already suggested by others), and to collect the results by $gene_id (which I guess was the idea behind looping through the file multiple times — assuming the data in IN aren't necessarily already sorted by ID).  Something like this:

while(<INlist>){ chomp; $scGeneids{$_} = ""; } ... while (<IN>){ chomp; my @columns=split /\t/; my $gene_id=$columns[0]; my $SNP_pos=$columns[2]; if ( exists $scGeneids{$gene_id} ){ $scGeneids{$gene_id} .= "$gene_id\t$SNP_pos\n"; # collect by +ID } } for my $key (sort keys %scGeneids) { print OUT $scGeneids{$key}; }

Replies are listed 'Best First'.
Re^2: help with loop
by AWallBuilder (Beadle) on Jan 18, 2012 at 12:30 UTC
    Thanks for your help. yes better use of the hash. But what does the ".=" mean in $scGeneids{$gene_id} .= "$gene_id\t$SNP_pos\n"; Thanks
      $foo .= $bar;
      means 
      $foo = $foo . $bar;
      means
      $foo = "$foo$bar";
      

      As already pointed out by Anonymous, the .= effectively appends to the string.

      Just to elaborate a little, consider the following (simplified) IN file:

      B ... 204248 ... A ... 204249 ... D ... 204250 ... C ... 204251 ... E ... 204252 ... A ... 204253 ... F ... 204254 ... C ... 204255 ... B ... 204256 ...

      If you go looking for the IDs A, B, C one after the other in several passes (as in your original approach), the hits will automatically be sorted by ID:

      A 204249 # first pas A 204253 B 204248 # second pass B 204256 C 204251 # third pass C 204255

      While if you do it in one pass, checking every entry against "if ( exists $scGeneids{$gene_id} )" to see if it's of interest, you'll get the IDs in the order they were encountered in IN, when you print them out immediately

      B 204248 A 204249 C 204251 A 204253 C 204255 B 204256

      This won't be an issue, of course, in case the entries are already sorted by ID.  Otherwise, it might not be what you want.

      You haven't said anything about the desired ordering of the results, nor whether IN is already sorted... so I thought it's worth pointing out anyway that if you wanted output similar to what your original multi-pass approach would have produced (if you had correctly reset the file in between passes), you could collect the results by ID before writing them out. I.e., every time you encounter a hit, you append the line to the respective hash entry.

      In other words, after having gone through the file, $scGeneids{A} will hold a long string with all A records, $scGeneids{B} all B records, and so on, so you can nicely print them out in sorted order.

      The same result could have been achieved by collecting the records in arrays (i.e. @{ $scGeneids{$gene_id} } ) and then joining them on output, but I thought the string-append variant is a tad easier to understand...