我在第一列中有一个带有重复值的制表符描述文件。第一列中的单个但重复的值对应于第二列中的多个值。它看起来像这样:
AAAAAAAAAA1 m081216|101|123
AAAAAAAAAA1 m081216|100|1987
AAAAAAAAAA1 m081216|927|463729
BBBBBBBBBB2 m081216|254|260489
BBBBBBBBBB2 m081216|475|1234
BBBBBBBBBB2 m081216|987|240
CCCCCCCCCC3 m081216|433|1000
CCCCCCCCCC3 m081216|902|366
CCCCCCCCCC3 m081216|724|193
对于第一列中的每种类型的序列,我试图打印到只包含与其对应的序列的文件。文件名应包括第一列中的重复序列以及第二列中与其对应的序列数。在上面的例子中,因此我将有3个文件,每个文件有3个序列。第一个文件的名称类似于“AAAAAAAAAA1.3.txt”,打开后如下所示:
m081216|101|123
m081216|100|1987
m081216|927|463729
我已经看过其他类似的问题,但是他们已经使用哈希回答了问题。我不认为我不能使用哈希,因为我需要保持列之间的关系数量。也许有办法使用散列哈希?我不确定。 到目前为止,这是我的代码。
use warnings;
use strict;
use List::MoreUtils 'true';
open(IN, "<", "/path/to/in_file") or die $!;
my @array;
my $queryID;
while(<IN>){
chomp;
my $OutputLine = $_;
processOutputLine($OutputLine);
}
sub processOutputLine {
my ($OutputLine) = @_;
my @Columns = split("\t", $OutputLine);
my ($queryID, $target) = @Columns;
push(@array, $target, "\n") unless grep{$queryID eq $_} @array;
my $delineator = "\n";
my $count = true { /$delineator/g } @array;
open(OUT, ">", "/path/to/out_$..$queryID.$count.txt") or die $!;
foreach(@array){
print OUT @array;
}
}
答案 0 :(得分:3)
我仍然会推荐哈希。但是,您将与相同ID相关的所有序列存储在匿名数组中,该数组是该ID键的值。这真的是两行代码。
use warnings;
use strict;
use feature qw(say);
my $filename = 'rep_seqs.txt'; # input file name
open my $in_fh, '<', $filename or die "Can't open $filename: $!";
my %seqs;
foreach my $line (<$in_fh>) {
chomp $line;
my ($id, $seq) = split /\t/, $line;
push @{$seqs{$id}}, $seq;
}
close $in_fh;
my $out_fh;
for (sort keys %seqs) {
my $outfile = $_ . '_' . scalar @{$seqs{$_}} . '.txt';
open $out_fh, '>', $outfile or do {
warn "Can't open $outfile: $!";
next;
};
say $out_fh $_ for @{$seqs{$_}};
}
close $out_fh;
通过输入,我得到了所需的文件,名为AA..._count.txt
,每个文件对应三行。如果分隔|
的项目应该被拆分,那么你可以在写出来时这样做,例如。
评论
我们$seqs{$id}
创建了密钥push
的匿名数组,如果没有,则
如果标签出现问题(转换为空格?),请使用' '
。见评论。
每个open
关闭并重新打开文件句柄,因此无需每次都关闭
split
的默认模式是' '
,也触发特定行为 - 它匹配“任何连续的空格”,并且还省略了前导空格。 (模式/ /
匹配单个空格,关闭' '
的这种特殊行为。)在split
页面上查看更精确的说明。因此,建议在拆分未指定数量的空格时使用' '
,因为在split
的情况下这有点惯用,可能是最常用的,并且是它的默认值。感谢Borodin提示此评论和更新(原始帖子具有等效的/\s+/
)。
请注意,在这种情况下,由于' '
是$_
的默认值,我们可以将其缩短一点
for (<$in_fh>) {
chomp;
my ($id, $seq) = split;
push @{$seqs{$id}}, $seq;
}