我在perl中有两个哈希,每个哈希由大约250,000个元素组成。我必须将两个散列中的每个元素相互比较,并对彼此相等的元素执行另一种操作。我有以下代码,可以进行约600亿次比较,因此需要很长时间才能完成:
foreach $key1 (keys %large_hash_1)
{
foreach $key2 (keys %large_hash_2)
{
if($some_other_var{$key1} == $some_other_var{$key2}) # so actually I compare another hash variable, using the keys from %large_hash_1 and %large_hash_2
{
# I print some stuff here to an output file using the $key1 and $key2 variables
}
}
}
有没有办法更快地做到这一点?
答案 0 :(得分:6)
可能是。看来您可以将问题重新表述为
找到所有成对的密钥
K1
和K2
:
$some_other_hash{K1} == $some_other_hash{K2}
K1
存在于%hash1
中,而K2
存在于%hash2
因此,让我们尝试一种方法,在该方法中,您首先找到第一个条件的解决方案,然后查看它们是否满足第二个条件。遍历所有密钥对都是O(n 2 ),但是我们已经有了一种策略,可以快速找到映射到相同哈希值的密钥:使用另一个哈希!
让我们构建%some_other_hash
的“反向哈希”,以便$hash7{VAL}
生成%some_other_hash
中所有键的列表,使得$some_other_hash{KEY} == VAL
:
push @{$hash7{ $some_other_hash{$_} }, $_ for keys %some_other_hash;
那是一个O(n)运算。接下来,我们需要找到映射到多个键的值。
foreach my $v (keys %hash7) {
@k = @{$hash7{$v}};
next if @k < 2;
...
}
如果找到这样的值,请检查某些键是否在%hash1
中,以及某些键是否在%hash2
中。
foreach my $v (keys %hash7) {
@k = @{$hash7{$v}};
next if @k < 2;
@k1 = grep { exists $hash1{$_} } @k;
@k2 = grep { exists $hash2{$_} } @k;
if (@k1 && @k2) {
foreach my $k1 (@k1) {
foreach my $k2 (@k2) {
print "$k1 from %hash1 and $k2 from %hash2 ",
"have the same value $v in %some_other_hash\n";
...
}
}
}
}
最坏的情况是,通常在%some_other_hash
中找到由多个键映射的值,该循环为O(mn)。根据您的数据,此搜索可能比遍历%hash1
和%hash2
中的所有键对都要快得多。