当尝试将一个文件中的记录与另一个文件中的记录进行匹配时,想法是使用hash ( also known as an associative array, set of key-value pairs, or dictionaries ) 来存储第一列与其余列之间的关系。实际上,创建以下关系:
file1: ABCD -> 0
ABDF -> 3
ACGFR -> 4
FGHTRSS -> 6
GFHTRSFS -> 7
file2: AB -> ID001
ACGFR -> ID001
DF -> ID001
...
ANH -> ID001
DFR -> ID002
AG -> ID002
...
KUH -> ID004
KOOL -> ID004
文件之间记录的实际匹配相当于确定
如果两个散列,这里 file1 和 file2 都有为每个 file1 记录定义的键。在这里我们可以看到ACGFR 是两者的键,因此我们可以匹配4 和ID001,以此类推其余键。
在 perl 中,我们可以通过分配成对的值来创建哈希:
my %hash = ( foo => 1, bar => 2 );
也可以使用引用创建哈希:
my $hash_ref = { foo => 1, bar => 2 };
可以使用keys 函数找到键,并且可以提取单个值:
my $val1 = $hash{ foo }; # regular hash
my $val2 = $hash_ref->{ foo }; # hash reference
可以使用exists 函数测试特定键是否是哈希的成员。
在不影响该背景的情况下,这是在 perl 中执行此操作的一种方法:
matchup_files.pl
#!/usr/bin/env perl
use warnings;
use strict;
my $usage = "usage: $0 file1 file2\n";
my ($file1, $file2) = @ARGV;
for my $file ($file1, $file2) {
die $usage unless defined $file && -f $file; # -f checks whether $file is an actual file
}
# Create mappings col2 -> col1
# col3 -> col1
# col4 -> col1
my $h1 = inverted_hash_file_on_first_column( $file1 );
my $h2 = hash_file_on_first_column( $file2 );
# Try to find matching pairs
my $matches = {};
for my $h1_key ( keys %$h1 ) {
my $h1_val = $h1->{$h1_key};
if ( exists $h2->{ $h1_val } ) {
# We have a match!
my $num = $h1_key;
my $id = $h2->{ $h1_val };
$matches->{ $num } = $id;
}
}
# Print them out in numerical order
for my $num ( sort { $a <=> $b } keys %$matches ) {
my $id = $matches->{$num};
print join(" ", $num, $id) . "\n";
}
exit 0; # Success
sub inverted_hash_file_on_first_column {
my ($file) = @_;
return _hash_file($file, 1);
}
sub hash_file_on_first_column {
my ($file) = @_;
return _hash_file($file, 0);
}
sub _hash_file {
my ($file, $inverted) = @_;
my $fhash = {};
open my $fh, "<", $file or die "Unable to open $file : $!";
while ( my $line = <$fh> ) {
my @fields = split /\s+/, $line; # Split line on whitespace
my $key = shift @fields; # First column
for my $field ( @fields ) {
if ( $inverted ) {
die "Duplicated field '$field'" if exists $fhash->{ $key };
$fhash->{ $key } = $field;
} else {
die "Duplicated field '$field'" if exists $fhash->{ $field };
$fhash->{ $field } = $key;
}
}
}
return $fhash;
}
输出
matchup_files.pl input1 input2
0 ID003
3 ID002
4 ID001
6 ID003
7 ID004