我正在努力访问/修改未知(即动态)深度的哈希值。
假设我正在读取文件中的度量表(长度,宽度,高度),然后计算面积和体积以创建如下的散列:
# #Length Width Height Results
my %results = (
'2' => {
'3' => {
'7' => {
'Area' => 6,
'Volume' => 42,
},
},
},
'6' => {
'4' => {
'2' => {
'Area' => 24,
'Volume' => 48,
},
},
},
);
我了解如何访问哈希中的单个项目,例如$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";
}
我知道你可以访问哈希的子哈希并得到它们的引用,所以在最后一个例子中,我可以遍历@hashkeys
,如果当前哈希在该键上有一个子哈希,则检查每个哈希值。如果是这样,保存对该子哈希的引用以用于下一次迭代。然而,这感觉很复杂,我怀疑已经有办法更轻松地做到这一点。
希望这足以理解我的问题,但如果没有,我可以尝试使用MWE。
感谢。
答案 0 :(得分: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
但请检查有关其他人已经提供的错误数据结构的评论,因为这是非常正确的。如果您仍然认为这是您需要的,至少使用for循环重写它,因为perl不会优化尾递归。
答案 1 :(得分:1)
看看“man perlvar”中的$;
。
http://perldoc.perl.org/perlvar.html#%24%3b
您可以使用这个想法将可变长度数组转换为单个键。
my %foo;
my (@KEYS)=(2,3,7);
$foo{ join( $; , @KEYS ) }{Area}=6;
$foo{ join( $; , @KEYS ) }{Volume}=42;