Как сгруппировать ряды последовательных чисел в Perl

#perl

#perl

Вопрос:

У меня есть ввод данных, который выглядит следующим образом:

 seq   75      T   G   - 
seq   3185    A   R    
seq   3382    A   R    
seq   4923    C   -     *
seq   4924    C   -     *
seq   4925    T   -     *
seq   5252    A   W    
seq   7400    T   C   -
seq   16710   C   -   - #
seq   18248   T   C   -
seq   18962   C   -     *
seq   18963   A   -     *
seq   18964   T   -     *
seq   18965   A   -     *
seq   19566   A   M    

The input above is already sorted at 2nd column.
  

Что я хочу сделать, так это:

  1. Обрабатывайте только строки, где 4-й столбец равен «-«.
  2. Если эти строки содержат последовательные позиции (2-й столбец), сгруппируйте их
  3. Представьте их как одну новую строку с наименьшей позицией в качестве новой позиции и конкатенацией сгруппированных букв в виде новых строк.

Следовательно, мы ожидаем получить этот вывод:

 seq   75      T   G   -   
seq   3185    A   R    
seq   3382    A   R    
seq   4923    CCT   -     **
seq   5252    A   W    
seq   7400    T   C   -
seq   16710   C   -   - #
seq   18248   T   C   -
seq   18962   CATA   -     **
seq   19566   A   M    

** Are the new lines/string formed by * line in first list (input)
# line is kept as it is because there is no consecutive position after that.
  

Я застрял со следующей логикой, не уверен, как поступить:

 while ( <> ) {
    chomp;

    my @els = split(/s /,$_);

    # Process indel
    my @temp = ();
    if ( $els[3] eq "-"  ) {
        push @temp, $_;
    }

     # How can I group them appropriately.
     print Dumper @temp ;

     # And print accordingly to input ordering

}
  

Ответ №1:

Это вариант отчета о нарушении контроля. Этот код, похоже, выполняет свою работу:

 use strict;
use warnings;

my($prev) = -100;
my($grp0) = $prev;
my($col2, $col4);

sub print_group
{
    my($grp0, $col2, $col3, $col4) = @_;
    printf "seq   %-5d  %-4s  %s  %sn", $grp0, $col2, $col3, $col4
        if ($grp0 > 0);
}

while (<>)
{
    chomp;
    my @els = split(/s /,$_);
    if ($els[3] ne "-")
    {
        print_group($grp0,   $col2,   "-",     $col4);
        print_group($els[1], $els[2], $els[3], $els[4]);
        $prev = -100;
        $grp0 = -100;
        $col2 = "";
        $col4 = "";
    }
    elsif ($els[1] == $prev   1)
    {
        $grp0  = $prev if $grp0 < 0;
        $prev  = $els[1];
        $col2 .= $els[2];
        $col4  = $els[4];
    }
    else
    {
        print_group($grp0, $col2, "-", $col4);
        $prev = $els[1];
        $grp0 = $els[1];
        $col2 = $els[2];
        $col4 = $els[4];
    }
}

print_group($grp0, $col2, $col4);
  

Пример вывода:

 seq   75     T     G  -
seq   3185   A     R   
seq   3382   A     R   
seq   4923   CCT   -   
seq   5252   A     W   
seq   7400   T     C  -
seq   16710  C     -  -
seq   18248  T     C  -
seq   18962  CATA  -   
seq   19566  A     M   
  

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

Может быть дьявольски сложно выполнить правильные условия — потребовалось несколько (слишком много) итераций, чтобы заставить этот код выдавать ожидаемый результат.