Perl:访问动态深度的哈希

SSi*_*ilk 0 perl hash hash-of-hashes

我正在努力访问/修改未知(即动态)深度的哈希值。

假设我正在从文件中读取一个测量表(长度,宽度,高度),然后计算“面积”和“体积”以创建如下所示的哈希:

#                       #Length  Width  Height  Results
my %results = (     
                        '2' => {        
                                '3' => {        
                                        '7' => {
                                                'Area' => 6,
                                                'Volume' => 42,
                                                },
                                        },
                                },
                        '6' => {        
                                '4' => {        
                                        '2' => {
                                                'Area' => 24,
                                                'Volume' => 48,
                                                },
                                        },
                                },
                        );
Run Code Online (Sandbox Code Playgroud)

我了解如何访问哈希中的单个项目(例如$results{2}{3}{7}{'Area'}会给我)6,或者我可以使用来检查是否已在输入文件中找到该度量组合exists $results{2}{3}{7}{'Area'}。但是,用{}括号括起来的符号假定我在编写代码时知道会有4层按键。

如果有更多或更少并且我仅在运行时发现该怎么办?例如,如果文件中只有Length和Width,您将如何制作随后访问哈希的代码$results{2}{3}{'Area'}

即给定一个哈希键和嵌套键的动态长度列表,该键在哈希中可能有也可能没有结果条目,您如何访问哈希以进行基本操作,例如检查该键组合是否具有值或修改该值?

我几乎想要这样的符号:

my @hashkeys = (2,3,7);

if exists ( $hash{join("->",@hashkeys)} ){
    print "Found it!\n";
}
Run Code Online (Sandbox Code Playgroud)

我知道您可以访问哈希的子哈希并获取它们的引用,因此在最后一个示例中,我可以进行遍历@hashkeys,检查每个哈希是否当前的哈希在该键处具有子哈希,如果是,则保存对该哈希的引用子哈希用于下一次迭代。但是,这感觉很复杂,我怀疑已经有一种方法可以更轻松地做到这一点。

希望这足以理解我的问题,但是如果没有,我可以尝试建立MWE。

谢谢。

Art*_*eev 5

因此,这是一个递归函数,它或多或少地执行您想要的操作:

sub fetch {
    my $ref = shift;
    my $key = shift;
    my @remaining_path = @_;

    return undef unless ref $ref;
    return undef unless defined $ref->{$key};
    return $ref->{$key} unless scalar @remaining_path;
    return fetch($ref->{$key}, @remaining_path);
}

fetch(\%results, 2, 3, 7, 'Volume');  # 42
fetch(\%results, 2, 3);               # hashref
fetch(\%results, 2, 3, 7, 'Area', 8); # undef
fetch(\%results, 2, 3, 8, 'Area');    # undef
Run Code Online (Sandbox Code Playgroud)

但是请检查其他人已经给出的有关不良数据结构的评论,因为这是真的。而且,如果您仍然认为这是您所需要的,则至少使用for循环将其重写,因为perl不会优化尾递归。