代码之家  ›  专栏  ›  技术社区  ›  Abdel

更有效地比较两个哈希中的所有元素

  •  1
  • Abdel  · 技术社区  · 6 年前

    我有两个Perl散列,每个散列由大约250000个元素组成。我必须比较两个哈希中的每个元素,并对彼此相等的元素执行另一个操作。我有下面的代码,它进行了大约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
                 }
            }
        }
    

    有没有一种方法可以更快地做到这一点?

    1 回复  |  直到 6 年前
        1
  •  6
  •   mob    6 年前

    可能。看起来你可以把问题重新表述为

    查找所有密钥对 K1 K2 这样:

    • $some_other_hash{K1} == $some_other_hash{K2}
    • K1 存在于 %hash1 K2 存在于 %hash2

    所以让我们尝试一种方法,首先找到第一个条件的解,然后看看它们是否满足第二个条件。遍历所有密钥对是o(n )但是我们已经有了一个快速找到映射到相同哈希值的键的策略:使用另一个哈希!

    让我们构建一个“反向散列” %some_other_hash 以便 $hash7{VAL} 生成中所有键的列表 %一些其他杂烩 这样 $some_other_hash{KEY} == VAL :

    push @{$hash7{ $some_other_hash{$_} }, $_ for keys %some_other_hash;
    

    那是个手术。接下来,我们需要找到映射到多个键的值。

    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";
                    ...
                }
            }
        }
    }
    

    最坏的情况是,通常在 %一些其他杂烩 它由多个键映射,这个循环是O(mn)。根据您的数据,此搜索可能比在 %HASH1 %HASH2 .