合并基于公共列的文件(但包含不同数量的记录)并将零写入非常见记录

时间:2013-01-30 20:29:56

标签: perl bash

我被困在我的Perl代码的一个非常有趣的部分,我必须根据公共列合并多个文件,但是这个公共列包含不同数量的记录,即一些文件可能存在于一个文件中,但是不在其他等等。

例如:以下是我的三个文件:

FileA.txt

ID  Value
 1   45
 2   56
 3   23

FileB.txt

ID  Value
 2   57
 3   65
 5   32

FileC.txt

ID  Value
 1   21
 3   68
 4   42

我的输出应该是一个组合表,如下所示:

ID  ValueA  ValueB  ValueC
 1   45       0      21
 2   56       57     0
 3   23       65     68
 4    0       0      42
 5    0       32     0

我尝试使用paste,但只是并排粘贴列表,而不考虑常用列。

我应该怎么做?

任何建议都将不胜感激。

2 个答案:

答案 0 :(得分:1)

使用哈希散列来记住部分表。主键是ID,内部哈希的键是文件。

#!/usr/bin/perl
use warnings;
use strict;
use feature qw(say);

use Data::Dumper;

my %table;
for my $letter (qw(A B C)) {
    open my $IN, '<', "File$letter.txt" or die "Cannot open: $!";
    <$IN>; # Skip the header
    while (<$IN>) {
        my ($id, $value) = split;
        $table{$id}{$letter} = $value;
    }
}

say "ID\tValueA\tValueB\tValueC";
for my $id (keys %table) {
    say $id, join"\t", q(), map $table{$id}{$_} // 0, qw(A B C);
}

答案 1 :(得分:0)

您可以初始化哈希(以ID作为键),并读取每个文件。当您阅读FileA.txt时,请输入类似的内容($ id和$ value是您从文件中获取的值):

$my_hash{$id} = {VALUE_A=>$value, VALUE_B=>0, VALUE_C=>0};

读取FileB.txt时,每行:

if( exists $my_hash{$id} ) {
  $my_hash{$id}->{VALUE_B=>$value};
}
else {
   $my_hash{$id} = {VALUE_A=>0, VALUE_B=>$value, VALUE_C=>0};
}

与FileC.txt完全相似:

if( exists $my_hash{$id} ) {
  $my_hash{$id}->{VALUE_C=>$value};
}
else {
   $my_hash{$id} = {VALUE_A=>0, VALUE_B=>0, VALUE_C=>$value};
}

最后,您拥有%my_hash

中的所有数据