0

この問題にうまく対処できているかどうかはわかりません。識別情報を含むファイルがあり、データベース名を持つそれらの識別情報の一部を含む 10 個のファイルがあります (ID ごとに同じですが、ファイル間で異なります)。私がやろうとしているのは、これらの 10 個のファイルのすべての Id を、ID が以前に一致した場合を除いて、ID のみを持つファイルと一致させることです。

これらの 10 個のファイルは次のようなものです。

File 1:
Id   Data Data Data Database_name 
Id1  ...  ...  ...    GenBank
...
Id20 ...  ...   ...   GenBank

File 2: 
Id   Data  Data Data Database_name
Id2  ...   ...  ...     IMG
Id30 ...   ...  ...     IMG
...

ファイルごとに、これら 2 つの値 (Id と Database_name) を二重キー付きハッシュに入れます。このコードの使用:

if ( -e "result_GenBank" ){
    print "Yes, it exist!!!! \n";
    open FILE,'<', "result_GenBank" or die "Error Importing GenBank";
    while (my $line=<FILE>){
        chomp ($line);
        my($ClustId, $M5, $Identity, $Evalue, $Bit_score, $Id, $Protein, $Specie, $DB ) = split /\t/g, $line; 

        $GenBank{$ClustId}{$DB}=1;
    }
    close FILE;
}

if ( -e "result_KEEG" ){
    print "Yes, it exist!!!! \n";
    open FILE,'<', "result_KEEG" or die "Error Importing KEEG";
    while (my $line=<FILE>){
        chomp ($line);
        my($ClustId, $M5, $Identity, $Evalue, $Bit_score, $Id, $Protein, $Specie, $DB ) = split /\t/g, $line; 

        $KEEG{$ClustId}{$DB}=1;
    }
    close FILE;
}

Id のみのファイルについては、ハッシュにも入れます。

 open FILE,'<', "Ids" or die "No Input";
while (my $line=<FILE>){
    chomp ($line);
    $key=$line;
    $total_ID{$key} = 1;

}
close FILE;

ここで、各二重キー付きハッシュ (Id および DB_name) を 1 つのキー (Id) のみを持つハッシュと比較するためのループが必要です。Id が一致する場合は、ID が以前に一致した場合を除き、Id と Db_name を出力して、2 つの異なる Db_name で同じ Id を持つことを回避します。

4

1 に答える 1

1

最初に、ID と DB のペアを重複排除して、各 ID が 1 つの DB にのみ関連付けられるようにすることを宣言します。したがって、ショートカットを使用して実行できます

$GenBank{$ClustId} = $DB;

ハッシュの構築中。

第二に、%GenBank%KEEGハッシュは本質的に同じデータ構造の一部です。これらの変数の命名は、実際にはそれらをより大きなハッシュのエントリにしたかったことを示唆しています。次に、そのひどいコードの重複を削除することもできます。

use feature 'say'; use autodie;

my @files = qw/GenBank KEEG/; # the physical files have e "result_" prefix

my %tables;
for my $file (grep { -e "result_$_" } @files ) {
    say STDERR "The $file file was found";
    open my $fh, '<', "result_$file";

    while (<$fh>){
        chomp;
        my($ClustId, $M5, $Identity, $Evalue, $Bit_score, $Id, $Protein, $Specie, $DB ) = split /\t/; 
        $table{$file}{$ClustId} = $DB;
    }
}

しかし待ってください: 後で ID を統一したい場合は、それらを同じハッシュに保存するだけです! また、現在のコードでは、特定の ID の最後の DB エントリが優先されます。最初のエントリが記憶されるように変更します。これは//、perl5 v10 以降で利用可能な defined-or 演算子を使えば簡単です。

my %DB_by_ID;
for my $file (grep { -e "result_$_" } qw/GenBank KEEG/ ) {
    ...;
    while (<$fh>){
        ...;
        $DB_by_ID{$ClustId} //= $DB;
    }
}

3 つ目のポイントは、ID ファイルはハッシュではなく配列を表しているということです。Idsファイル内のエントリを重複排除する場合は、一般にuniqfromを使用するのが最適List::MoreUtilsです。

use List::MoreUtils 'uniq';

my @IDs;

open my $fh, "<", "Ids"; # no error handling neccessary with autodie
while (<$fh>) {
  chomp;
  push @IDs, $_;
}

@IDs = uniq @IDs;

上記のコードがひどくばかげていることは認めざるを得ません。これが、次を使用する理由File::Slurpです。

use List::MoreUtils 'uniq';
use File::Slurp;

my @IDs = uniq read_file('Ids', chomp => 1);

あとは、%DB_by_IDで指定された ID を使用してテーブルを反復処理@IDsし、結果を出力するだけです。これは次のようになります

for my $id (@IDs) {
  if (not exists $DB_by_ID{$id}) {
    warn "no entry for ID=$id";
    next;
  }
  say join "\t", $id, $DB_by_ID{$id};
}
于 2013-07-18T11:46:59.207 に答える