如何存储散列路径以在perl中重用它们?

如何存储散列路径以在perl中重用它们?,perl,hash,path,store,Perl,Hash,Path,Store,假设我在散列中嵌套了大量元素(来自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) = @_; ret

假设我在散列中嵌套了大量元素(来自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。这里有一个这样的例子,它为你们提供了一个单一的地方来改变你们的路径,并且在操作上是相当方便的。我还将set/get方法简化为一个单独的组合子方法,该组合子方法执行两种操作:

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
a
b
y
z
这样做的目的是将两个常量值(
PATH1
PATH2
)设置为所需的值。这在编译时发生。接下来,在
BEGIN
块中,我们根据文本字符串(“element_”)动态创建子例程,并在该名称的末尾附加一个元素。然后,我们将其指定为中的typeglob,并使用一个具有所需功能的匿名子例程。这也发生在编译时。我的$elem…行的
中的每个条目都将创建一个子元素
X()

如果路径发生更改,只需在
use constant
块中进行更改

现在,您似乎正在使用一个对象,那么为什么不直接在其中转储数据,而不是传递任意的hashref呢?这里有一个例子。请注意,我正在
使用5.10.0-ing,以便我可以使用定义的or运算符(以及
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;
输出:

aaa
bbb
yyy
zzz
a
b
y
z

注意:如果不小心使用,直接使用符号表可能相当危险。覆盖你不想去做的事情是微不足道的,这会导致各种各样的小的或大的悲伤。这就是为什么
没有使用严格的“refs”
的原因。我将其范围限定为可能的最小块,并(隐式地)确保没有其他
element.*
symtab(符号表)条目存在
strict
捕获像这样可能的违规行为,这就是为什么我们总是建议始终使用它,并且只在尽可能小的范围内禁用它,只在“违反规则”所需的部分以及绝对需要禁用它时才禁用它。

您可以使用配置文件来定义“路径”。在getter/setter/其他相关函数中,您可以只引用配置文件键。因此,无论何时更改JSON密钥,您只需在配置文件中进行更改,而不是在所有函数中进行更改,但是,如果必须更改两个位置而不是一个位置,那么额外的运行时费用值得节省吗?您可以通过生成getter和setter来避免额外的运行时费用。您需要与组织内的人员讨论API的标准化问题。把这样的事情转换成一次性的很容易,但是如果这总是一个猜测游戏,那么这项工作就不值得了。我只是更新了这个问题,因为我认为我没有正确地解释我想做什么。我很感谢你花时间写下答案,这肯定能帮助我学到更多,但我认为它并没有回答我想问的问题。谢谢