您提到了 Python、Perl 和 Awk。
在所有三个中,想法都是一样的:使用散列来存储值。
散列就像数组,除了每个条目都用一个键而不是位置来索引。在散列中,只能有一个带有该键的条目。正因为如此,散列被用来检查之前是否出现过值。这是一个快速的 Perl 示例:
my %value_hash;
for my $value ( qw(one two three one three four) ) {
if ( exists $value_hash{$value} ) {
print "I've seen the value $value before\n";
}
else {
print "The value of $value is new\n";
$value_hash{$value} = 1;
}
}
这将打印出:
The value of one is new
The value of two is new
The value of three is new
I've seen the value of one before
I've seen the value of three before
The value of four is new
首先,您需要两个循环:一个循环遍历所有文件,另一个循环遍历特定文件的每一行。
for my $file_name ( @file_list ) {
open my $file_fh, "<", $file_name
or die qw(File $file_name doesn't exist);
while (my $line = <$file_fh>) {
chomp $line;
...
}
}
接下来,我们将介绍每个氨基酸总数的哈希值和这些氨基酸的跟踪哈希值:
use strict;
use warnings;
use autodie;
my %total_amino_acids;
my @file_list = qw(file1 file2); #Your list of files
for my $file_name ( @file_list ) {
open my $file_fh, "<", $file_name;
my %seen_amino_acid_before; # "Initialize" hash which tracks seen
while (my $line = <$file_fh>) {
chomp $line;
my ( $location, $amino_acid ) = split $line;
if ( not %seen_amino_acid_before{$amino_acid} ) {
$total_amino_acids{$amino_acid} += 1;
}
}
}
现在,我假设当您说unique时,您仅在谈论氨基酸而不是位置。这split
是拆分两个值,我只看氨基酸。如果位置也很重要,则必须将其包含在%seen_amino_acid_before
散列的键中。这很棘手,因为我可以想象以下内容:
54 LEU
54 LEU
054.00 LEU
这些是不同的字符串,但都具有相同的信息。您需要确保标准化位置/氨基酸键。
while (my $line = <$file_fh>) {
chomp $line;
my ( $location, $amino_acid ) = split $line;
my $amino_acid_key = sprinf "%04d-%s", $location, uc $amino_acid;
if ( not %seen_amino_acid_before{$amino_acid_key} ) {
$total_amino_acids{$amino_acid} += 1;
}
}
在上面,我正在创建一个$amino_acid_key
. 我使用sprintf
将我的数字部分格式化为零填充的十进制和氨基酸为大写。这边走:
54 LEU
54 leu
054.00 Leu
都是关键0054-LEU
。这样,您在文件中输入数据的方式就不会影响您的结果。这可能是一个完全不必要的步骤,但您应该始终考虑这一点。例如,如果您的数据是计算机生成的,这可能不是问题。如果您的数据是由一群过度劳累的研究生在半夜输入的,您可能需要担心格式。
现在,您只需要一个循环来读取数据:
for my $amino_acid ( sort keys %total_amino_acids ) {
printf "total no:of %4s - %4d\n", $amino_acid, $total_amino_acids{$amino_acid};
}
请注意,我曾经printf
帮助格式化总计,因此它们将被排列。