Mesclando linhas com valores comuns

2

Estou tentando combinar correspondências emparelhadas em um arquivo de texto para que eu possa encontrar todas as correspondências em um grupo: por exemplo,

meu arquivo contém duas colunas separadas por tabulações como esta:

Simon John
Simon Paul
Steve Simon
Graham Dave
Dave Jason
Paul Simon
Peter Derek

Eu gostaria que um arquivo exibisse os grupos, por exemplo

Simon John Paul Steve
Graham Dave Jason
Peter Derek

Qualquer ajuda seria realmente útil !! Experimentei o script abaixo, mas parece que recebo correspondências duplicadas (por exemplo, o Simon aparece duas vezes em linhas separadas no arquivo out) e leva muito tempo para ser executado. Idealmente, se há um tempo para fazê-lo no bash seria melhor.

use strict;

my(@homologs,$genefile,@temp,$line,$found,$i,$j);

$genefile="Arabidopsis_combined.txt";

open(IN,"<$genefile") or die "cannot open $genefile\n";
$j=0;
while(!eof(IN)){
    $line=readline *IN;
    chomp($line);
    @temp=split /\t/,$line;
    $i=0;
    $found="F";
    while($i<@homologs){
        if($temp[0]~~@{$homologs[$i]}){
            if($temp[1]~~@{$homologs[$i]}){}
            else{push @{$homologs[$i]},$temp[1];}
            $found="T"; 
            }
        if($temp[1]~~@{$homologs[$i]}){
            if($temp[0]~~@{$homologs[$i]}){}
            else{push @{$homologs[$i]},$temp[0];}
            $found="T";         
            }
        $i++;       
        }
    if($found eq "F"){
        push @homologs,[@temp];
        }
    print $j."\n";
    $j++;
    }
close(IN);

print "Number of groups of homologs: ".@homologs."\n";

open(OUT,">homologs.txt");
$i=0;
while($i<@homologs){
    print OUT "@{$homologs[$i]}"."\n";
    $i++;   
    }
close(OUT);
    
por funnings 27.04.2015 / 15:32

1 resposta

4

Este é um problema padrão de encontrar componentes conectados em um gráfico não direcionado. Desde que você marcou sua pergunta com perl :

#!/usr/bin/env perl

use v5.10;                                       
use strict;
use warnings;

use Graph::Undirected;

my $g = Graph::Undirected->new;

while (<>) {
    chomp;
    $g->add_edge( split /\t/ );
}

for ( $g->connected_components() ) {
    say join ' ', @$_;
}

Ou seu equivalente na linha de comando:

perl -MGraph::Undirected -F'\t' -lane '
  BEGIN{$g=Graph::Undirected->new}
  $g->add_edge(@F);
  END{$,=" ";print @$_ for $g->connected_components}'
    
por 27.04.2015 / 15:54