在 Perl 中,参考文件和一系列文件之间的映射

2024-01-04

我想在 Perl 中映射两个数据集。我有一个不变的数据集(ref 1),必须从一系列文件(1-20)中提取其他数据以匹配 ref1。

Ref1
ID1    ID2
1       HZ
1       HX
1       HY
2       C  
2       HZ
2       N

File 1
ID2    ID3
HA      5 
HB      4
HC      7
N       2

File 2
ID2    ID3
C      9
HZ     11
N      0

理想输出:

ID1 ID2 ID3 
1   HZ   5
1   HX   4 
1   HY   7
2   C    9
2   HZ   11
2   N    0

匹配发生在 ref1 中 ID2 的第一个字母与 file1 中 ID2 的第一个字母之间,直到完成所有 ID1 条目的匹配,然后打开 file2 并与所有编号为 2 的 ID1 进行匹配。文件名的格式为 number001.txt 、number002.txt等,因此可以从文件名中检索ID1。

我希望这是有道理的。我是 Perl 的初学者,这是我到目前为止所拥有的:

#!/usr/bin/perl
use strict;
use warnings;

my $ref1 = 'test.txt';
my $input_path = '/path/';

open my $fh, '<' $ref1 or die "Can't read $ref1: $!";
chomp (my @ref1 = <$fh>);

my %hash = @ref1;

my @filehandles;
for ($i=0; $i<20, $i++) {
    local *FILE;
    open(FILE, ">number$i.txt") or die $!;
    push(@filehandles, *FILE);
}

任何建议都会非常有帮助。


这并没有按照您的想法进行:

chomp (my @ref1 = <$fh>);
my %hash = @ref1;

在这里转置键/值并没有什么魔力——所以你要做的就是得到一个如下所示的哈希值:

      '2       C  ' => '2       HZ',
      'ID1    ID2' => '1       HZ',
      '1       HX' => '1       HY',
      '2       N' => undef

我打赌那不是你想要的。

我怀疑你可能想要的是:

    my %ref1;
    while ( <$input> ) {
        chomp;
        my ( $key, $value ) = split;
        push ( @{$ref1{$key}}, $value );
    }
    print Dumper \%ref1;

您还将打开文件以便在第二个循环中进行写入。您可能也不想这样做。

我会选择类似的东西:

#!/usr/bin/perl
use strict;
use warnings;

use Data::Dumper;

my $ref1       = 'ref1.txt';
my $input_path = '/path/';

open my $ref1_fh, '<', $ref1 or die "Can't read $ref1: $!";

my %ref1;
while (<$ref1_fh>) {
    chomp;
    next if m/ID/;
    my ( $key, $value ) = split;
    my $zeropadded = sprintf( "%03d", $key );
    my ($firstletter) = ( $value =~ m/^(\w)/ );
    push( @{ $ref1{$zeropadded}{$firstletter} }, $value );

}

print Dumper \%ref1;

print join( "\t", "ID1", "ID2", "ID3" ), "\n";
foreach my $filename ( glob("number*.txt") ) {
    my ($ref_num) = ( $filename =~ m/number(\d+)/ );
    open( my $input, "<", $filename ) or warn $!;
    while (<$input>) {
        chomp;
        my ( $key, $value ) = split;
        my ($firstletter) = ( $key =~ m/^(\w)/ );
        if ( defined $ref1{$ref_num}{$firstletter}
            and @{ $ref1{$ref_num}{$firstletter} } )
        {
            my $refkey = pop( @{ $ref1{$ref_num}{$firstletter} } );

            print join( "\t", int $ref_num, $refkey, $value ), "\n";
        }
    }
    close($input);
}

我已将“ref”数字转换为零填充,因此它直接匹配文件名,因为您指定的文件名是number001.txt匹配1 in ref1.

我还要插入以下内容$ref1进入数组的哈希值,键入您要查找的第一个字母 - 弹出“查找”值直到为空。

因此我们得到:

ID1 ID2 ID3
1   HY  5
1   HX  4
1   HZ  7
2   C   9
2   HZ  11
2   N   0
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Perl 中,参考文件和一系列文件之间的映射 的相关文章

随机推荐