比较两个散列哈希的最佳方法?

时间:2012-01-09 15:55:49

标签: sql perl hash compare

现在我有两个散列哈希值,一个是我通过解析日志文件创建的,另一个是我从SQL中获取的。我需要比较它们以确定日志文件中的记录是否已存在于数据库中。现在我正在迭代每个元素来比较它们:

foreach my $i(@record)
{
    foreach my $a(@{$data})
    {
        if ($i->{port} eq $a->{port} and $i->{name} eq $a->{name})
        {
            print "match found $i->{name}, updating record in table\n";
        }
        else
        {
            print "no match found for $tableDate $i->{port} $i->{owner} $i->{name} adding record to table\n";
            executeStatement("INSERT INTO client_usage (date, port, owner, name, emailed) VALUES (\'$tableDate\', \'$i->{port}\', \'$i->{owner}\', \'$i->{name}\', '0')");

        }
    }

}

当然,随着数据库变大,这需要很长时间才能完成。有更有效的方法吗?我可以直接比较密钥吗?

2 个答案:

答案 0 :(得分:2)

你不只是哈希哈希。您有两个列表,每个列表中的每个元素都包含哈希哈希值。因此,您必须将列表中的每个项目与另一个列表中的每个项目进行比较。你的算法效率是O 2 - 不是因为它是散列的散列,而是因为你将一个列表中的每一行与另一个列表中的每一行进行比较。

是否可以浏览您的列表并将其转换为由端口和名称键入的哈希值?这样,您可以浏览每个列表一次以创建索引哈希值,然后通过哈希值进行一次比较。

例如,要从记录中创建哈希:

my %record_hash;
foreach my $record_item (@record) {
   my $name = $record_item->{name};
   my $data = $record_item->{data}
   my $record_hash{$name:$data} = \$record_item  #Or something like this...
}

接下来,您将对数据列表执行相同的操作:

my %data_hash;
foreach my $data_item (@{$data}) {
   my $name = $data_item->{name};
   my $data = $data_item->{data}
   my $data_hash{$name:$data} = \$data_item  #Or something like this...
}

现在,您只需查看一次新创建的哈希:

foreach my $key (keys %record_hash) {
   if (exists $data_hash{$key}) {
       print "match found $i->{name}, updating record in table\n";
   }
   else {
      print "no match found for $tableDate $i->{port} $i->{owner} $i->{name} adding record to table\n";
      executeStatement("INSERT INTO client_usage (date, port, owner, name, emailed) VALUES (\'$tableDate\', \'$i->{port}\', \'$i->{owner}\', \'$i->{name}\', '0')");

   }
}

假设您在一个列表中有1000个元素,在另一个列表中有500个元素。您的原始算法必须循环500 * 1000次(50万次)。通过创建索引哈希,您必须循环2(500 + 1000)次(约3000次)。

另一种可能性:由于您已经在使用SQL数据库,为什么不将整个事情作为SQL查询。也就是说,不要获取记录。而是遍历您的数据,并为每个数据项获取记录。如果记录存在,则更新它。如果没有,您创建一个新的。这可能更快,因为你没有把整个事情变成一个列表,以便把它变成一个哈希。

tie SQL databases直接哈希的方法。这也许是一个很好的方式。

您使用的是Perl-DBI吗?

答案 1 :(得分:0)

如何使用Data :: Difference:

use Data:Difference qw(data_diff);

my @diff = data_diff(\%hash_a, \%hash_b);

@diff = (
    { 'a' => 'value', 'path' => [ 'data' ] }, # exists in 'a' but not in 'b'
    { 'b' => 'value', 'path' => [ 'data' ] }, # exists in 'b' not in 'a'
);