我有两个以制表符分隔的文件,超过一百万行,我需要根据第一列查找有多少值是常见的,有多少是特定于其中一个文件。
我正在尝试使用以下代码在Perl中执行此操作,但它无法正常工作。
我需要考虑给定文件大小的计算时间。
有人可以帮我纠正这个问题,或建议更有效的方法吗?
K00134:78_1 272 1 3057610
K00134:78_0 272 1 3057610
K00134:78_2 272 1 3057610
K00134:78_3 272 1 3057610
K00134:78_1 272 1 3057610
K00134:78_5 272 1 3057610
K00134:78_6 272 1 3057610
K00134:78_3 272 1 3057610
use strict;
use warnings;
my %Set;
open (SET1, "<", "left.txt") or die "cannot open file";
while (<SET1>) {
my @line = split (/\t/, $_);
$Set{$line[0]} = $line[1];
}
my @k = keys %Set;
foreach my $key (@k) {
print "$key, $Set{$key}\n";
}
close SET1;
open (SET2, "<", "right.txt") or die "cannot open file";
print "common:\n";
while (<SET2>) {
chomp;
if ( exists $Set{"$_"} ) {
print "$Set{$_}\n";
}
}
close SET2;
输出应如下所示,列出基于第一列的公共字段 -
common lines -
K00134:78_1 272 1 3057610
K00134:78_3 272 1 3057610
不常见的行 - left.txt
K00134:78_0 272 1 3057610
K00134:78_2 272 1 3057610
不常见的行 - right.txt
K00134:78_5 272 1 3057610
K00134:78_6 272 1 3057610
另外,我也试图从每个文件中添加不匹配作为输出,但我不确定它是否可能给定文件的大小。谢谢!
答案 0 :(得分:2)
您的第二个读取循环代码错误。它应该通过制表符分开并检查。将其更改为:
while (<SET2>) {
my @line = split (/\t/, $_);
print $_ if exists $Set{$line[0]};
}
它会起作用。你的方法还可以。由于您只想比较第一列,因此您无需将$ Set {}的值设置为第二列($ line [1]),您只需将其设置为&#39;&# 39;为了节省记忆。另外,为了节省内存,请确保left.txt是两者中最小的一个。这是一个有效的例子:
use strict;
use warnings;
my %Set;
open (SET1, "<", "left.txt") or die "cannot open file";
while (<SET1>) {
my @line = split (/\t/, $_);
$Set{$line[0]} = '';
}
close SET1;
open (SET2, "<", "right.txt") or die "cannot open file";
print "common:\n";
while (<SET2>) {
my @line = split (/\t/, $_);
print $_ if exists $Set{$line[0]};
}
close SET2;
编辑 - 这是另一种可以提供你想要的方法
use strict;
use warnings;
my %Set;
sub readFile {
my ($fn, $bit) = @_;
open (F, "<" ,$fn) or die "can't open file";
while (<F>) {
my ($k) = split (/\t/, $_);
$Set{$k} = $Set{$k} || [0, $_];
$Set{$k}[0] |= $bit;
}
close F;
}
sub showByBit {
my ($k, $bit) = @_;
foreach my $key (@{$k}) {
my $a = $Set{$key};
print $a->[1] if $a->[0] == $bit;
}
}
readFile('left.txt', 1);
readFile('right.txt', 2);
my @k = keys %Set;
print "common lines -\n";
showByBit(\@k, 3);
print "uncommon lines - left.txt\n";
showByBit(\@k, 1);
print "uncommon lines - right.txt\n";
showByBit(\@k, 2);