2016-07-22 8 views
0

Я работаю с входным файлом, который содержит последовательности с разделителями табуляции. Группы последовательностей разделяются разрывами строк. Файл выглядит следующим образом:Как подсчитать количество ключей, существующих в хеше?

TAGC  TAGC  TAGC  HELP 
    TAGC  TAGC  TAGC 
    TAGC  HELP 
    TAGC 

Вот код, у меня есть:

use strict; 
    use warnings; 

    open(INFILE, "<", "/path/to/infile.txt") or die $!; 

    my %hash = ( 
      TAGC => 'THIS_EXISTS', 
      GCTA => 'THIS_DOESNT_EXIST', 
    ); 

    while (my $line = <INFILE>){ 
      chomp $line; 
      my $hash; 
      my @elements = split "\t", $line; 
      open my $out, '>', "/path/to/outfile.txt" or die $!; 
      foreach my $sequence(@elements){ 
        if (exists $hash{$sequence}){ 
         print $out ">$sequence\n$hash{$sequence}\n"; 
        } 
        else 
        } 
         $count++; 
         print "Doesn't exist ", $count, "\n"; 
        } 
      } 
    } 

Как я могу сказать, сколько последовательностей существуют, прежде чем напечатать? Мне нужно поместить эту информацию в имя выходного файла.

В идеале у меня бы была переменная, которую я мог бы включить в имя файла. К сожалению, я не могу просто взять скаляр из @elements, потому что есть некоторые последовательности, которые не будут распечатаны. Когда я пытаюсь нажать клавиши, которые существуют в массиве, а затем распечатать скаляр этого массива, я до сих пор не получаю результаты, которые мне нужны. Вот что я пытался (все переменные, которые должны быть глобальными):

open my $out, '>', "/path/to/file.$number.txt" or die $!;  
    foreach my $sequence(@elements){ 
      if (exists $hash{$sequence}){ 
        push(@Array, $hash{$sequence}, "\n"); 
        my $number = @Array; 
        print $out ">$sequence\n$hash{$sequence}\n"; 
      #.... 

Спасибо за помощь. Действительно ценю это.

ответ

2
my $sequences = grep exists $hash{$_}, @elements; 
open my $out, '>', "/path/to/outfile_containing_$sequences.txt" or die $!; 

В контексте списка grep фильтрует список по критерию; в скалярном контексте он возвращает количество элементов, удовлетворяющих критерию.

+0

Это замечательно. Благодарю. – Rob

0

Самый простой способ - отслеживать, сколько ключей вы печатаете в переменной, и как только закончите цикл, просто переименуйте файл с вычисленным номером. Для этого Perl имеет встроенную функцию. Код будет выглядеть примерно так:

use strict; 
use warnings; 

open(INFILE, "<", "/path/to/infile.txt") or die $!; 

my %hash = ( 
     TAGC => 'THIS_EXISTS', 
     GCTA => 'THIS_DOESNT_EXIST', 
); 
my $ammt; 

while (my $line = <INFILE>){ 
     chomp $line; 
     my $hash; 
     my @elements = split "\t", $line; 
     open my $out, '>', "/path/to/outfile.txt" or die $!; 
     foreach my $sequence(@elements){ 
       if (exists $hash{$sequence}){ 
        print $out ">$sequence\n$hash{$sequence}\n"; 
        $ammt++; 
       } 
       else 
       } 
       print "Doesn't exist ", $count, "\n"; 
       } 
     } 
} 

rename "/path/to/outfile.txt", "/path/to/outfile${ammt}.txt" or die $!; 

Я удалил переменную $count, так как он не объявлен в коде (нечеткое будет жаловаться, что). Here's официальный документ для rename. Поскольку он возвращает True или False, вы можете проверить, что он был успешным или нет.

Кстати, следует помнить, что:

push(@Array, $hash{$sequence}, "\n"); 

хранит два элемента ($hash{$sequence} и \n), так что счетчик будет в два раза, как это должно быть.