如何获得与散列哈希中的散列引用密钥相关联的密钥? [英] How to get the key associated with a hash reference's key in a hash of hashes?

查看:247
本文介绍了如何获得与散列哈希中的散列引用密钥相关联的密钥?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

 #散列的%属性散列的内容
#内部散列是对名为%属性的散列的散列引用

$ 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'
}
}
}

我创建了一个数组来保存%属性(也就是%属性中的值/散列引用)的键:

  @list =排序键%属性; 

我试图迭代 @list 并在%properties 中查找外部散列的关联关键字。因此,例如,如果 / DriveA / archive / 是数组中的下一项,我想查找与该值相关的哈希键, / DriveA ,来自%属性,假定取消内部哈希。



I创建一个反向哈希,它输出以下内容:

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

...使用此代码...

  foreach my $ item(@list){
my%rhash = reverse%properties; #反转散列的散列,所以值是键
print Dumper(\%rhash);

$ / code>



问题1:



<鉴于以上所述,我将如何解引用散列,以便我可以在散列引用中找到 $ item ,以便我可以确定关联值(而不是散列引用值)。

如果 $ item ='/ DriveA / archive /',我想捕获 '/ DriveA'%属性的变量中,所以它可以从子程序返回。



我知道内部散列需要解除引用,我只是不知道该怎么做。我已阅读 perlref perldsc perllol ,但



谢谢。

解决方案

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

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

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






解决实际的技术问题:


  • 你从一个哈希引用开始(基本上是一个用C语言指针)。然后你将这个散列引用作为一个键分配给一个散列。




    • p>在Perl中对一个哈希引用进行了字符串化时,它会变成该引用的字符串表示 - 这就是您在Data :: Dumper时看到的 HASH(0x2002f244)字符串你的反向散列。

  • 在技术层面上,我将散列引用的字符串表示重新转换为散列引用本身?

  • perl.org/perlfaq4.html#How-can-I-use-a-reference-as-a-hash-key? rel =nofollow> Perl FAQ 4 。据我所知,你不能轻易地将散列引用的字符串表示转换回散列引用本身。
  • 如果你绝对必须(我强烈建议不要 - 相反,使用答案顶部的解决方案) - 您可以使用 Devel :: Pointer CPAN模块。



    A使用该模块的解决方案显示在此PerlMonks主题中。







另一个解决方案可能是使用 Tie :: RefHash 模块使用实际的散列引用而不是它们的字符串表示法作为键。这在第8.5.1章中有记录。 O'Reilly的Programming Perl,3rd edition中的引用不作为哈希键。我会建议不要那么疯狂。


In an attempt to help me learn Perl, I built the following data structure, where the inner hash (/DriveA/archive, etc.) is a hash reference:

#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'
        }
    }
}

I created an array to hold the keys for %attributes (aka the values/hash reference in %properties) using:

@list = sort keys %attributes;

I'm trying to iterate over the elements in @list and find the associated key for the outer hash in %properties. So, for example, if /DriveA/archive/ is the next item in the array, I want to find the hash key associated with that value, /DriveA, from %properties, assuming dereference of the inner hash.

I created a reverse hash, which outputs the following...

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

...using this code...

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

Question 1:

Given the above, how would I dereference the hash so I can find $item in the hash reference so I can determine the associated value (not the hash reference value).

If $item = '/DriveA/archive/', I want to capture '/DriveA' in a variable from %properties so it can be returned from a subroutine.

I know the inner hash needs to be dereferenced, I'm just not sure how to do it. I've read through perlref, perldsc, and perllol, but I haven't been able to find the answer.

Thanks.

解决方案

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.

这篇关于如何获得与散列哈希中的散列引用密钥相关联的密钥?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆