我有一个带有以下数据的制表符分隔文件。第一列表示ID,第二列是该ID的值。
294535 k__Bacteria
294535 p__Firmicutes
294535 c__Clostridia
294535 o__Clostridiales
294535 f__Lachnospiraceae
537364 k__Bacteria
537364 p__Planctomycetes
537364 c__vadinHA49
7652 k__Bacteria
7652 p__Proteobacteria
7652 c__Gammaproteobacteria
7652 o__Thiotrichales
7652 f__Thiotrichaceae
7652 g__Leucothrix
520836 k__Bacteria
520836 p__Firmicutes
520836 c__Clostridia
520836 o__Clostridiales
520836 f__Lachnospiraceae
320231 k__Bacteria
我希望以下列格式输出,即只有具有相同ID的多个项目中的最后两项。
294535 o__Clostridiales
294535 f__Lachnospiraceae
537364 p__Planctomycetes
537364 c__vadinHA49
7652 f__Thiotrichaceae
7652 g__Leucothrix
520836 o__Clostridiales
520836 f__Lachnospiraceae
任何人都可以帮我找到一个好的解决方案吗?
我尝试逐行读取文件时使用索引和for
循环,但它没有发生。这是我的循环结构,下面没有工作。
while ( <TEMPIN> ) {
chomp;
my ($ID, $tax) = split('\t', $_);
push (@taxID, $ID);
push (@taxa, $tax);
for ( $i, $i <= $#taxID, $i++ ) {
if ( $taxID[$i] = $taxID[$i+1] ) {
next unless $taxID[$i] != $taxID[$i+1];
}
else {
print "$taxID[$i]\t$taxa[$i]\t$taxID[$i-1]\t$taxa[$i-1]\n";
}
}
}
答案 0 :(得分:2)
这会按照你的要求行事。它为散列%data
中的每个ID保留所有值的列表,并在@ids
中保持ID的原始出现顺序以防重要
输出循环只是修剪除了每个条目的最后两个项目之外的所有项目并打印它们
程序需要输入文件的路径作为命令行参数,并将输出打印到STDOUT
use strict;
use warnings 'all';
my ( %data, @ids );
while ( <> ) {
next unless /\S/;
my ( $id, $val ) = split;
push @ids, $id unless $data{$id};
push @{ $data{$id} }, $val;
}
for my $id ( @ids ) {
my $vals = $data{$id};
splice @{$vals}, 0, -2;
print "$id\t$_\n" for @{$vals};
}
294535 o__Clostridiales
294535 f__Lachnospiraceae
537364 p__Planctomycetes
537364 c__vadinHA49
7652 f__Thiotrichaceae
7652 g__Leucothrix
520836 o__Clostridiales
520836 f__Lachnospiraceae
320231 k__Bacteria