【问题标题】:Perl, Compare two hashes - Can't use string ("1") as a HASH refPerl,比较两个哈希 - 不能使用字符串(“1”)作为哈希引用
【发布时间】:2014-03-31 15:55:23
【问题描述】:

请多多包涵,我从来没有在网上问过编程问题,所以我不知道如何解释自己。无论如何,继续提问。

我的目标是比较两个哈希,每个哈希都是一个数据库的内容,并更新本地数据库的远程数据库条目的记录,其中远程数据库的 ident 的值与本地的 ident 记录不匹配,这被命名为 unqiue_ident。

当远程不再匹配时,我目前必须将本地数据库的状态更新为禁用。我需要使用本地数据库的身份作为条件。例如更新本地设置 status = 'disabled' where ident = '1'。

我可以使用下面的代码将哈希值与肯定结果进行比较。

use strict;

my %remote_hash = (
    ident    => '1001',
    name     => 'remote hash name',
);
my %local_hash  = (
    ident         => '1',
    remote_ident  => '1001',
    name          => 'remote hash name',  
    status        => 'active'
);

foreach (sort keys %local_hash){
    unless (exists $remote_hash{$_}){
        print "$_: not found in Remote hash\n";
        next; 
    }
}

但是,我不明白如何使用代码提取 ident 以更新 db 条目。我尝试过的一种方法,对我来说最有意义的是:

foreach my $test (sort keys %local_hash){
    unless (exists $remote_hash{$_}){
        print "$_: not found in Remote hash\n";
        print $test{ident};
        next; 
    }
}

这样,我会收到以下错误:Can't use string ("1") as a HASH ref while "strict refs" in use 此外,如果我不调用 ident,并将代码运行为:

foreach my $test (sort keys %local_hash){
    unless (exists $remote_hash{$_}){
        print "$_: not found in Remote hash\n";
        next; 
    }
}

它破坏了整个事情,并将所有记录视为不匹配。 我不确定如何进一步处理这个问题。有人可以帮助我解决我遇到的问题吗?


编辑 - 回复 simbabque。我认为我严重歪曲了哈希值。 以下是相关哈希的更好细分。

当转储远程哈希时,这是我得到的。

$VAR1 = '1001';
$VAR2 = 'NAME 1';
$VAR3 = '1002';
$VAR4 = 'NAME 2';
$VAR5 = '1003';
$VAR6 = 'NAME 3';
$VAR7 = '1004';
$VAR8 = 'NAME 4';
$VAR9 = '1005';

转储本地哈希时,我得到:

$VAR1 = [
          {
            'ident'             => '1',
            'group_name'            => 'NAME 1',
            'status'        => 'active',
            'unique_id'             => '1001',
          },

对于远程哈希,我通过执行以下操作将数组转换为哈希:

my %remote_hash;
foreach my $data_pair( @remote_hash_list){
    my $ident = $data_pair->{ident};
    my $group_name = $data_pair->{sched_group};
       $group_name =~ s/\s+$//g;

    $remote_hash{$ident} = $group_name;
}

我有点犹豫,所以我不确定这是否是将数组转换为哈希的正确方法。如果我转储数组 @remote_hash_list 我得到:

$VAR1 = {
          'ident'       => 1001,
          'sched_group' => 'NAME 1',
        };

当我尝试您解释的方法时,$hash{value};是空的。 不过,我认为这与哈希的构建方式有关?

【问题讨论】:

  • 很难理解你在做什么;您是否要确定除了 ident 和 status 之外的键中的两个哈希之间是否存在任何差异?或者也许只是身份?
  • 我只想看到我在本地db中记录的unique_ident是否在远程哈希中看到。如果没有,不管是否有任何其他信息匹配,禁用本地数据库上的记录。这是因为,如果远程中的 ident 发生更改,则会在本地数据库中为其创建一条新记录。希望这是有道理的。
  • 为了清楚起见,您显示的远程哈希转储是@remote_hash_list 还是%remote_hash 的转储?并且您创建 %remote_hash 只是为了这个问题所涉及的查找,还是您还需要它用于其他目的?
  • (顺便说一句,在转储散列或数组时,如果转储对它们的引用,则会得到更好的输出 - 例如Dumper( \%remote_hash ),因此它们不会首先被展平为列表。)
  • 转储属于@remote_hash_list

标签: perl loops for-loop hash foreach


【解决方案1】:

这里有几个问题:

  • 您正在遍历一个键列表并将每个键放入$test,但您正在查看$_;该变量未在您的循环中使用。它可能有旧数据。
  • 您正在使用标量 $test(这是来自 %local_hash 的键之一)作为另一个哈希。

您要做的是在比较哈希后查看远程密钥ident

根据你对问题的描述,你需要做的就是:

if ($local_hash{status} ne $remote_hash{status}){
  update( $remote_hash{ident}, $remote_hash{status} );
}

对于这两个哈希,您甚至不需要循环。

如果您有一堆哈希,您可以在哈希上循环执行此操作,就像远程查询的结果一样。

【讨论】:

  • 尝试您的方法时,hashref 始终为空。这是我的错,因为我认为我严重歪曲了哈希值。我在原始问题中包含了对哈希的更好描述。
猜你喜欢
  • 1970-01-01
  • 2018-04-06
  • 1970-01-01
  • 2017-01-06
  • 2011-12-19
  • 1970-01-01
  • 2016-09-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多