Как я могу читать и анализировать порции данных в хэш-массив Perl? - PullRequest
1 голос
/ 16 апреля 2010

У меня есть данные, которые выглядят так:

#info
#info2

1:SRX004541
Submitter: UT-MGS, UT-MGS
Study: Glossina morsitans transcript sequencing project(SRP000741)
Sample: Glossina morsitans(SRS002835)
Instrument: Illumina Genome Analyzer
Total: 1 run, 8.3M spots, 299.9M bases
Run #1: SRR016086, 8330172 spots, 299886192 bases

2:SRX004540
Submitter: UT-MGS
Study: Anopheles stephensi transcript sequencing project(SRP000747)
Sample: Anopheles stephensi(SRS002864)
Instrument: Solexa 1G Genome Analyzer
Total: 1 run, 8.4M spots, 401M bases
Run #1: SRR017875, 8354743 spots, 401027664 bases

3:SRX002521
Submitter: UT-MGS
Study: Massive transcriptional start site mapping of human cells under hypoxic conditions.(SRP000403)
Sample: Human DLD-1  tissue culture cell line(SRS001843)
Instrument: Solexa 1G Genome Analyzer
Total: 6 runs, 27.1M spots, 977M bases
Run #1: SRR013356, 4801519 spots, 172854684 bases
Run #2: SRR013357, 3603355 spots, 129720780 bases
Run #3: SRR013358, 3459692 spots, 124548912 bases
Run #4: SRR013360, 5219342 spots, 187896312 bases
Run #5: SRR013361, 5140152 spots, 185045472 bases
Run #6: SRR013370, 4916054 spots, 176977944 bases

Я хочу создать хеш массива с первой строкой каждого чанка в качестве ключей. и SR ## часть строк с "^ Run" в качестве члена массива:

$VAR = {
     'SRX004541' => ['SRR016086'], 
     # etc
}

Но почему моя конструкция не работает. И это должен быть лучший способ сделать это.

use Data::Dumper;
my %bighash;
my $head = "";
my @temp = ();

while ( <> ) {
    chomp;
    next if (/^\#/);


    if ( /^\d{1,2}:(\w+)/ ) { 
print "$1\n";
      $head = $1;


    }
    elsif (/^Run \#\d+: (\w+),.*/){ 
print "\t$1\n";
      push @temp, $1;
    }
    elsif (/^$/) {
         push @{$bighash{$head}}, [@temp];
         @temp =();
    }

}               


print Dumper \%bighash ;

Ответы [ 5 ]

5 голосов
/ 16 апреля 2010

Альтернативный способ сделать такой разбор - это прочитать целые абзацы. Для получения дополнительной информации о разделителе входной записи ($/) см. perlvar .

Например:

use strict;
use warnings;
use Data::Dumper qw(Dumper);
my %bighash;

{
    local $/ = "\n\n"; # Read entire paragraphs.
    while (my $paragraph = <>){
        # Filter out comments and handle extra blank lines between sections.
        my @lines = grep {/\S/ and not /^\#/} split /\n/, $paragraph;
        next unless @lines;

        # Extract the key and the SRR* items.
        my $key = $lines[0];
        $key =~ s/^\d+://;
        $bighash{$key} = [map { /^Run \#\d+: +(SRR\d+)/ ? $1 : () } @lines];
    }
}

print Dumper(\%bighash);
2 голосов
/ 16 апреля 2010

Заменить

push @{$bighash{$head}}, [@temp];

на

push @{$bighash{$head}}, @temp;

У вас есть только один массив на $head значение, верно?Второй оператор добавляет все значения в @temp в arrayref в $bighash{$head}.Форма first , с другой стороны, создает ссылку на массив из элементов в @temp и толкает , которые на $bighash{$head}, давая вам arrayref из arrayrefs.

В качестве альтернативы вы можете захотеть

$bighash{$head} = [@temp];

Если вы ожидаете встретить каждое значение $head один раз.

1 голос
/ 16 апреля 2010

Основываясь на вашем коде, вот один из способов сделать это

my $head;
my %result;
while (<>) {
    chomp;
    next if (/^\#/);

    if ( /^\d{1,2}:(\w+)/ ) {
        $result{$1} = []; 
        $head = $1; # $head will be used to know which key the following values
                    # will be assigned to
    }
    elsif (/^Run \#\d+: (\w+),.*/) {
        push(@{$result{$head}},$1); #Add the number found to the array that is assigned to the                        
                                    #last key found
    } 
}
0 голосов
/ 16 апреля 2010

Код выглядит правильно, но я настоятельно рекомендую добавить:

use warnings
use strict

во всем, кроме самых тривиальных лайнеров, также добавьте

 elsif ($head && /^$/) {

до вашего последнего состояния, чтобы поймать проблемы.

0 голосов
/ 16 апреля 2010

Проблемы с вашим конечным автоматом, я думаю, вы можете использовать эту логику:

if(!$head)
{
  # seek and get head
} 
else
{
  if (!$total) 
  {
    # seek and get total
  }
  else
  {
    # seek run
    # if found :
      # push run to temp and decrease total
      # if total eq 0 :
        # push temp to bighash
        # reset head, total and temp
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...