我有两个数组(Array1和Array2)。 Array1包含大约20,000个非唯一元素。 Array2包含大约90,000个唯一元素。我试图计算Array1中的元素数量,这些元素也显示为Array2的元素。下面的perl脚本成功但缓慢。是否有另一种方法可以计算Array2中存在的可能比这更快的Array1元素的数量?
#!/usr/bin/perl
use strict;
use warnings;
use autodie;
# This program counts the total number of elements in one array that exist in a separate array.
my $Original_Array_File = "U:/Perl/MasterArray.txt";
# Read in the master file into an array.
open my $file, '<', $Original_Array_File or die $!;
my @Array2 = <$file>;
close $file;
my $path = "C:/Files by Year/1993";
chdir($path) or die "Cant chdir to $path $!";
for my $new_file ( grep -f, glob('*.txt') ) {
open my ($new_fh), '<', $new_file;
my @Array1 = <$new_file>;
my @matched_array_count ;
foreach @Array1 {
++$matched_array_count if ($_ ~~ @Array2 ) ;
}
答案 0 :(得分:4)
性能问题的主要来源是:
foreach @Array1 {
++$matched_array_count if ($_ ~~ @Array2 );
}
的行为
$string ~~ @array
就像
grep { $string ~~ $_ } @array
和
$string1 ~~ $string2
就像
$string1 eq $string2
将这些内容与原始代码段放在一起,我们得到类似的内容:
foreach my $string1 @Array1 {
++$matched_array_count if grep { $string1 eq $_ } @Array2;
}
换句话说,取@Array1
中的第一个元素并将其与@Array2
中的每个元素进行比较,然后取@Array1
中的第二个元素,将其与@Array2
中的每个元素进行比较,依此类推。这可以解决
scalar @Array1 * scalar @Array2
比较,总计大约18亿。
通常在Perl中完成的方式是使用哈希。单个散列查找比搜索数组中的每个元素要快得多。基本算法是:
exists
查看哈希中是否有匹配的密钥。在您的特定情况下,您可以将U:/Perl/MasterArray.txt
的内容加载到哈希中,然后执行
scalar @Array1
哈希查找,或~2,000。这将比现在快得多。
以下是在Linux词典文件中搜索单词的示例:
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
my $file = '/usr/share/dict/linux.words';
open my $fh, '<', $file or die "Failed to open '$file': $!";
my %haystack = map { chomp; $_ => 1 } <$fh>;
my $count;
while (<DATA>) {
chomp;
$count++ if exists $haystack{$_};
}
say $count;
__DATA__
foo
bar
foobar
fubar
3
(显然,“foobar”是一个单词。“FUBAR”是一个单词,但小写的“fubar”不是。)
您还应该知道,从Perl 5.18.0开始,the smartmatch family of features are now experimental:
智能匹配,在v5.10.0中添加并在v5.10.1中进行了重大修订,一直是一个常规投诉点。尽管有许多方法可用,但它也证明了Perl的用户和实现者都存在问题和困惑。关于如何最好地解决问题,已经提出了许多建议。 很明显,smartmatch几乎肯定会在将来改变或消失。不建议依赖其当前行为。 (强调添加)
答案 1 :(得分:0)
看起来你想比较很多文件。
您可以将其拆分为使用每个文件一个线程的线程池。或者,如果您受到更多内存限制,则可以将其中一个数组拆分为多个部分,并将每个部分发送到不同的线程。