我有一个2文本文件。 file1 包含ID:
0 ABCD
3 ABDF
4 ACGFR
6 ABCD
7 GFHTRSFS
file2 :
ID001 AB ACGFR DF FD GF TYFJ ANH
ID002 DFR AG ABDF HGT MNJ POI YUI
ID003 DGT JHY ABCD YTRE NHYT PPOOI IUYNB
ID004 GFHTRSFS MJU UHY IUJ POL KUH KOOL
如果文件1的第二列与文件2中的任何条目匹配,那么文件2的第一列应该是它的答案。
输出应该是:
0 ID003
3 ID002
4 ID001
6 ID003
7 ID004
(file1(ABCD)的第2列找到与ID003的第3行的第3行匹配。因此,ID003应该是它的答案)。
我也尝试过其他帖子的例子,但不知怎的,它们与此不匹配。
任何帮助都将不胜感激。
亲切的问候
答案 0 :(得分:1)
当尝试将一个文件中的记录与另一个文件中的记录进行匹配时,我们的想法是使用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