,可以说我在哈希中嵌套了大量元素(来自JSON(。我想为他们准备好和固定器。例如:
sub set_element_x{
my ($self, $hash_ref, $value) = @_;
$hash_ref->{'path1'}->{'path2'}->{'x'} = $value;
return;
}
sub get_element_x{
my ($self, $hash_ref, $value) = @_;
return $hash_ref->{'path1'}->{'path2'}->{'x'};
}
是否有一种标准的方式来处理这条路,以防您只需要更改它们,以防JSON结构发生变化?
我想添加更多信息,因为我认为我没有正确解释自己。
我希望能够存储在公共位置此代码以访问JSON中的值:
->{'path1'}->{'path2'}->{'x'}
将来可能会更改为:
->{'path1_1'}->{'path2_1'}->{'path3_1'}->{'x_1'}
pd:如果使用@Stevieb的答案提供的代码,我将无法保存所需的结构。添加这两行:
print Dumper($href) . "n";
print to_json($href) . "n";
屈服于:
$VAR1 = {
'PATH1' => {
'PATH2' => {
'a' => 'aaa',
'b' => 'bbb',
'y' => 'yyy',
'z' => 'zzz'
}
}
};
{"PATH1":{"PATH2":{"a":"aaa","b":"bbb","y":"yyy","z":"zzz"}}}
所以总结一下。我希望能够存储一个复杂结构的哈希路径,并具有许多未固定的键。
ikegami
,在注释中指定自动生成您的潜艇。这是一个例子,它为您提供了一个单个改变路径的地方,并且在操作方面相当平稳。我还将您的集合/获取方法减少到了同时执行两项操作的单个组合sub:
use warnings;
use strict;
use constant {
PATH1 => '/home/steveb/PATH1',
PATH2 => '/home/steveb/PATH2',
};
BEGIN {
for my $elem (qw(a b y z)){
my $sub_name = "element_$elem";
no strict 'refs';
*$sub_name = sub {
my ($hash_ref, $value) = @_;
$hash_ref->{PATH1}{PATH2}{$elem} = $value if defined $value;
return $hash_ref->{PATH1}{PATH2}{$elem};
}
}
}
my $href = {};
element_a($href, 'aaa');
element_b($href, 'bbb');
element_y($href, 'yyy');
element_z($href, 'zzz');
print element_a($href) . "n";
print element_b($href) . "n";
print element_y($href) . "n";
print element_z($href) . "n";
输出:
aaa
bbb
yyy
zzz
做什么,将两个常数值(PATH1
和PATH2
(设置为您想要的值。这发生在编译时。接下来,在BEGIN
块中,我们基于文本字符串(" element_"(动态创建子例程,并在该名称的末尾附加元素。然后,我们将其分配为具有匿名子例程的符号表中的typeglob,并具有所需的功能。这也发生在编译时。for my $elem...
行中的每个条目都将创建element_X()
sub。
如果您的路径发生了变化,则只需在use constant
块中更改它。
现在,您似乎正在使用一个对象,那么为什么不只是将数据倒在其中,而不是通过任意的hashref传递呢?这是一个例子。请注意,我是use 5.10.0;
-ing,以便我可以使用//=
定义或操作员(以及say
功能(:
软件包:
package Blah;
use warnings;
use strict;
use 5.10.0;
use constant {
PATH1 => '/home/steveb/path1',
PATH2 => '/home/steveb/path2',
};
BEGIN {
for my $elem (qw(a b y z)){
my $sub_name = "element_$elem";
no strict 'refs';
*$sub_name = sub {
my ($self, $value) = @_;
return $self->{PATH1}{PATH2}{$elem} //= $value;
}
}
}
sub new {return bless {}, shift};
1;
脚本示例:
use warnings;
use strict;
use 5.10.0;
use Blah;
my $blah = Blah->new;
$blah->element_a('a');
$blah->element_b('b');
$blah->element_y('y');
$blah->element_z('z');
say $blah->element_a;
say $blah->element_b;
say $blah->element_y;
say $blah->element_z;
输出:
a
b
y
z
注意:如果不进行极端谨慎,直接使用符号表可能很危险。覆盖您并非故意的事情是微不足道的,这可能会导致各种小小的或大的悲伤。这就是为什么正在使用no strict 'refs'
的原因。我将其瞄准了可能的最小块,并且(隐式(确保没有其他element_*
Symtab(符号表(条目存在。strict
会捕获这样的违规行为,这就是为什么我们始终推荐它,并且仅将其禁用尽可能小的范围,只有"违反规则"所需的零件,并且只有绝对必需的禁用范围。
如果您的路径具有fix depth =>您可以将其用作数组(或数组参考(并使用此结构,例如:
sub get_element_x {
my ($hash_ref, $path) = @_;
return $hash_ref->{$path->[0]}->{$path->[1]}->{$path->[2]};
}