我有两个(非常大的)文本文件。在运行时方面,最快的方法是创建第三个文件,其中包含未出现在file2中的所有file1行?
因此,如果file1包含:
Sally Joe Tom Suzie
file2包含:
Sally Suzie Harry Tom
然后输出文件应包含:
Joe
答案 0 :(得分:13)
创建一个包含文件2中每一行的hashmap。然后,对于文件1中的每一行,如果它不在hashmap中,则输出它。这将是O(N),这是您可以实现的最佳效率等级,因为您必须阅读输入。
Perl实现:
#!/usr/bin/env perl
use warnings;
use strict;
use Carp ();
my $file1 = 'file1.txt';
my $file2 = 'file2.txt';
my %map;
{
open my $in, '<',$file2 or Carp::croak("Cant open $file2");
while (<$in>) {
$map{$_} = 1;
}
close($in) or Carp::carp("error closing $file2");
}
{
open my $in,'<', $file1 or Carp::croak("Cant open $file1");
while (<$in>) {
if (!$map{$_}) {
print $_;
}
}
close $in or Carp::carp("error closing $file1");
}
如果文件2太大以至于hashmap不适合内存,那么我们手头有一个不同的问题。然后可能的解决方案是在文件2的块上使用上述解决方案(小到足以装入内存),将结果输出到临时文件。如果文件1和文件2之间有足够的匹配,那么总输出应该是合理的大小。为了计算最终结果,我们在临时文件中执行行的交集,即对于最终结果中的行,它必须出现在每个临时文件中。
答案 1 :(得分:7)
不是Perl但有效:
diff <(sort file1) <(sort file2)
答案 2 :(得分:5)
我很惊讶没人提出最节省内存的方法,即分别对两个文件进行排序,然后执行列表合并。如果您使用的是Unix,以下3个简单命令可以快速执行您所需的操作:
sort < file1 > file1.sorted
sort < file2 > file2.sorted
comm -2 -3 file1.sorted file2.sorted > differences
如果文件太大以至于Perl必须将VM分页以将所有行加载到哈希表中,这种技术将更多更快。否则,哈希表 - 基于方法应该更快。
如果您使用的是Unix,最好使用系统的外部sort
命令,因为它对内存使用情况很敏感 - 使用Perl的sort()
需要将文件的全部内容读入内存。
如果您使用的是Windows,请注意提供的sort
命令不区分大小写且无法关闭!此外,没有comm
命令在Windows上,所以你需要自己动手 - 用上面的第三行替换:
perl subtract_sets.pl file1.sorted file2.sorted > differences.txt
#!/usr/bin/perl
open my $f1, '<', $ARGV[0] or die;
open my $f2, '<', $ARGV[1] or die;
my $x = <$f1>;
my $y = <$f2>;
while (defined $x && defined $y) {
if ($x lt $y) {
print $x;
$x = <$f1>;
} elsif ($y lt $x) {
print $y;
$y = <$f2>;
} else {
# Lines match
$x = <$f1>;
$y = <$f2>;
}
}
while (defined $x) {
print $x;
$x = <$f1>;
}
while (defined $y) {
print $y;
$y = <$f2>;
}
答案 3 :(得分:4)
#!/usr/bin/perl
use warnings;
use strict;
open(my $alpha, '<', 'file1') || die "Couldn't open file1";
open(my $beta, '<' , 'file2') || die "Couldn't open file2";
my %data;
map {$data{$_} = 1} <$alpha>;
map {print $_ unless $data{$_}} <$beta>;
答案 4 :(得分:2)
对你来说有什么特别的?比你的RAM更大?您的基本答案是使用哈希值,如果文件大于您的RAM,那么您需要使用hash tied to a dbm。
答案 5 :(得分:2)
只是一些效率基准:
10k行,每行最多10个字符的随机字符串。
Rate slipset marcog
slipset 47.6/s -- -16%
marcog 56.7/s 19% --
100k行,每行最多10个字符的随机字符串。
Rate slipset marcog
slipset 3.02/s -- -34%
marcog 4.60/s 52% -
1000k行,每行最多10个字符的随机字符串。
s/iter slipset marcog
slipset 4.09 -- -33%
marcog 2.75 49% --
1k行,每行最多100个字符的随机字符串。
Rate slipset marcog
slipset 379/s -- -12%
marcog 431/s 14% --
100k行,每行最多100个字符的随机字符串
Rate slipset marcog
slipset 2.15/s -- -30%
marcog 3.08/s 44% --
1k行,每行最多1000个字符的随机字符串
Rate slipset marcog
slipset 133/s -- -10%
marcog 148/s 11% --
100k行,每行最多1000个字符的随机字符串
Rate slipset marcog
slipset 1.01/s -- -18%
marcog 1.22/s 22% --
内存效率
Marcog:100k行,每行最多1000个字符的随机字符串:
Memory usage summary: heap total: 163_259_635, heap peak: 61_536_800, stack peak: 17_648
total calls total memory failed calls
malloc| 307_425 162_378_090 0
realloc| 1_461 96_878 0 (nomove:1_218, dec:1_026, free:0)
calloc| 12_762 784_667 0
free| 307_598 155_133_460
Slipset:100k行,每行最多1000个字符的随机字符串:
Memory usage summary: heap total: 647_103_469, heap peak: 118_445_776, stack peak: 17_648
total calls total memory failed calls
malloc| 508_089 186_752_811 0
realloc| 399_907 459_553_775 0 (nomove:334_169, dec:196_380, free:0)
calloc| 12_765 796_883 0
free| 507_584 256_315_688