【问题标题】:How to get the key associated with a hash reference's key in a hash of hashes?如何在哈希哈希中获取与哈希引用的键关联的键?
【发布时间】:2014-01-30 19:44:25
【问题描述】:

为了帮助我学习 Perl,我构建了以下数据结构,其中内部哈希(/DriveA/archive 等)是哈希引用:

#The contents of the %properties hash of hashes
#The inner hash is a hash reference to a hash named %attributes

$VAR1 = {
    '/DriveA' => {
        '/DriveA/archive/' => {
            'MaxSize' => '20GB',
            'Size' => '19GB',
            'Free' => '5'
        },
        '/DriveA/current/' => {
            'MaxSize' => '20GB',
            'Size' => '12GB',
            'Free' => '40'
        }
    },
    '/DriveB' => {
        '/DriveB/archive/' => {
            'MaxSize' => '8GB',
            'Size' => '6GB',
            'Free' => '25'
        },
        '/DriveB/current/' => {
            'MaxSize' => '80GB',
            'Size' => '20GB',
            'Free' => '75'
        }
    },
    '/DriveC' => {
        '/DriveC/' => {
            'MaxSize' => '20GB',
            'Size' => '10GB',
            'Free' => '50'
        }
    }
}

我创建了一个数组来保存 %attributes 的键(又名 %properties 中的值/哈希引用),使用:

@list = sort keys %attributes;

我正在尝试遍历@list 中的元素并在%properties 中找到外部哈希的关联键。因此,例如,如果 /DriveA/archive/ 是数组中的下一项,我想从 %properties 中找到与该值关联的哈希键 /DriveA,假设取消引用内部哈希。

我创建了一个反向哈希,它输出以下内容...

$VAR1 = {
    'HASH(0x2002f244)' => '/DriveB',
    'HASH(0x2002f388)' => '/DriveC',
    'HASH(0x2002f1e4)' => '/DriveA'
}

...使用此代码...

foreach my $item (@list) {
    my %rhash = reverse %properties;     # Reverse the hash of hashes so value is key
    print Dumper(\%rhash);
}

问题一:

鉴于上述情况,我将如何取消引用哈希,以便我可以在哈希引用中找到$item,这样我就可以确定关联的值(而不是哈希引用值)。

如果是$item = '/DriveA/archive/',我想在%properties 的变量中捕获'/DriveA',以便可以从子程序返回。

我知道内部散列需要被取消引用,我只是不知道该怎么做。我已经阅读了perlrefperldscperllol,但一直没有找到答案。

谢谢。

【问题讨论】:

  • 据我所知,您正试图从基本上是引用的字符串表示形式中获取数据结构引用。不要那样做。那种方式是疯狂的。

标签: perl hash perl-data-structures hash-of-hashes hashref


【解决方案1】:

最简单的做法就是直接通过遍历数据结构生成反向键:

my %reverse_keys;
foreach my $outer_key (keys %properties) {
    my $inner_hashref = $properties->{$outer_key};
    my %reverse_map = map { ($_ => $outer_key) } keys %$inner_hashref;
    %reverse_keys = (%reverse_keys, %reverse_map);
}

理想情况下,您甚至可以在将数据存储到 %properties 的同时直接生成 %reverse_keys,因此您不需要上面的额外遍历代码。


解决您的实际技术问题:

  • 您从哈希引用开始(基本上是 C 语言中的指针)。

  • 然后您将该哈希引用作为键分配给哈希。

    • 将某些内容分配为哈希键会将其放入字符串上下文(标量上下文的一种特殊情况)。

    • 当您在 Perl 中对哈希引用进行字符串化时,它会转换为该引用的字符串表示形式 - 这是您在 Data::Dumper 反向哈希时看到的 HASH(0x2002f244) 字符串。

      李>
  • 您要问的是,在技术层面上,“如何将哈希引用的字符串表示形式转换回哈希引用本身?”

  • Perl FAQ 4 对此进行了介绍。据我所知,您不能轻易地将哈希引用的字符串表示形式转换回哈希引用本身。

  • 如果您绝对必须(我强烈建议您不要这样做 - 而是使用答案顶部的解决方案) - 您可以使用 Devel::Pointer CPAN 模块来做到这一点。

    this PerlMonks thread 中显示了使用该模块的解决方案。


另一个解决方案可能是使用Tie::RefHash 模块来使用实际的哈希引用而不是它们的字符串表示作为键。这在第 8.5.1 章中有记录。 O'Reilly 的“Programming Perl, 3rd edition”中的“References Don't Work as Hash Keys”。我也建议不要这样做。

【讨论】:

  • 我不一定要尝试创建反向哈希,这只是我知道使用该值访问密钥的唯一方法。我可以访问的数据是/MyDriveA/archive/,我需要访问上一级的密钥,以便将/MyDriveA 分配给一个变量。如果唯一的方法,或者最好/最安全的方法是迭代结构,那么如果我在创建 %properties 时不返回并执行它,我会尝试一下。
  • 另外,如果字符串真的总是遵循这种模式,保证,您可以通过正则表达式从“DriveA/archive”获取“DriveA”,而无需任何数据结构。
猜你喜欢
  • 2021-12-30
  • 2011-07-01
  • 1970-01-01
  • 2010-12-19
  • 2019-03-27
  • 2011-05-27
  • 2012-08-17
  • 1970-01-01
  • 2013-03-22
相关资源
最近更新 更多