2

为了帮助我学习 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;

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

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

$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/',我想'/DriveA'从变量中捕获,%properties以便可以从子例程返回。

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

谢谢。

4

1 回答 1

1

The easiest thing to do is to just generate the reverse keys directly by traversing the data structure:

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);
}

Ideally, you can even generate %reverse_keys directly at the same time you're stashing data into %properties, so you don't need that extra traversal code above.


To address your actual technical question:

  • You are starting with a hash reference (basically, a pointer in C vernacular).

  • Then you assign that hash reference as a key into a hash.

    • Assigning something as a hash key puts it into a string context (a special case of scalar context).

    • When you stringify a hash reference in Perl, it gets turned into a string representation of that reference - that's your HASH(0x2002f244) string you see when you Data::Dumper your reverse hash.

  • What you're asking is, on a technical level, is "how do I convert the string representation of a hash reference back into the hash reference itself?"

  • This is covered in Perl FAQ 4. As far as I'm aware, you can NOT easily convert the string representation of a hash reference back into the hash reference itself.

  • If you absolutely must (which I strongly recommend against - instead, use the solution at the top of the answer) - you can do so using Devel::Pointer CPAN module.

    A solution using that module is shown in this PerlMonks thread.


An additional solution may be to use Tie::RefHash module to use actual hash references instead of their string representations as keys. This is documented in Chapter 8.5.1. "References Don't Work as Hash Keys" of O'Reilly's "Programming Perl, 3rd edition". I would recommend against that bit of madness as well.

于 2014-01-12T00:41:15.157 回答