perl 检查嵌套哈希引用
perl check nested hash reference
我有以下代码:
#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;
my $site = "test.com";
my $data = {
"test" => 1
};
my $user = defined($data->{addons}->{$site}->{username}) ? $data->{addons}->{$site}->{username} : "nothing";
print Dumper($data);
结果:
$VAR1 = {
'test' => 1,
'addons' => {
'test.com' => {}
}
};
如您所见,检查用户是否在嵌套结构中定义实际上创建了一个空键。我的问题是如何在不定义键的情况下检查哈希引用。
你正在为“autovivification”绊倒。 Perl 会自动在您尝试访问的数据结构中创建中间层。你可以在这里看到它的实际效果:
$ perl -MData::Dumper -E'if (!$foo->{bar}->{baz}){}; say Dumper $foo'
$VAR1 = {
'bar' => {}
};
为了检查$foo->{bar}->{baz}
是否为真,Perl创建了$foo->{bar}
。这使得 创建 复杂的数据结构变得容易,但在查询它们时可能会出现问题。
但是看看这个:
$ perl -M-autovivification -MData::Dumper -E'if (!$foo->{bar}->{baz}){}; say Dumper $foo'
$VAR1 = undef;
autovivification pragma 可以很容易地关闭部分代码中的自动生成。所以只需添加:
no autovivification;
在导致问题的代码块中。
更新: 还有一种手动方法,它涉及检查数据结构的每一层,一旦发现与你的不匹配的东西就停止查找寻找:
$ perl -MData::Dumper -E'if ("HASH" eq ref $foo and exists $foo->{bar} and !$foo->{bar}->{baz}){}; say Dumper $foo'
$VAR1 = undef;
如Dave Cross pointed out, this is autovivification。通常情况下,你不需要担心它,除非你在某个时候根据这个散列键的存在做出假设,或者如果你的数据集太大以至于需要非常小心的内存调节。
你可以使用no autovivification
编译指示,最好是在有限的词法范围内,例如:
my $user;
{ # no autovivification is limited to this block
no autovivification;
$user = $data->{addon}{$site}{username} // "nothing";
}
//
就是defined-or operator,在这种情况下使用方便。
但对于像这样的简单问题,您可能会采用更简单的解决方案:
my $user;
if ( defined $data->{addon}{$site} ) {
$user = $data->{addon}{$site}{username} // "nothing";
}
我有以下代码:
#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;
my $site = "test.com";
my $data = {
"test" => 1
};
my $user = defined($data->{addons}->{$site}->{username}) ? $data->{addons}->{$site}->{username} : "nothing";
print Dumper($data);
结果:
$VAR1 = {
'test' => 1,
'addons' => {
'test.com' => {}
}
};
如您所见,检查用户是否在嵌套结构中定义实际上创建了一个空键。我的问题是如何在不定义键的情况下检查哈希引用。
你正在为“autovivification”绊倒。 Perl 会自动在您尝试访问的数据结构中创建中间层。你可以在这里看到它的实际效果:
$ perl -MData::Dumper -E'if (!$foo->{bar}->{baz}){}; say Dumper $foo'
$VAR1 = {
'bar' => {}
};
为了检查$foo->{bar}->{baz}
是否为真,Perl创建了$foo->{bar}
。这使得 创建 复杂的数据结构变得容易,但在查询它们时可能会出现问题。
但是看看这个:
$ perl -M-autovivification -MData::Dumper -E'if (!$foo->{bar}->{baz}){}; say Dumper $foo'
$VAR1 = undef;
autovivification pragma 可以很容易地关闭部分代码中的自动生成。所以只需添加:
no autovivification;
在导致问题的代码块中。
更新: 还有一种手动方法,它涉及检查数据结构的每一层,一旦发现与你的不匹配的东西就停止查找寻找:
$ perl -MData::Dumper -E'if ("HASH" eq ref $foo and exists $foo->{bar} and !$foo->{bar}->{baz}){}; say Dumper $foo'
$VAR1 = undef;
如Dave Cross pointed out, this is autovivification。通常情况下,你不需要担心它,除非你在某个时候根据这个散列键的存在做出假设,或者如果你的数据集太大以至于需要非常小心的内存调节。
你可以使用no autovivification
编译指示,最好是在有限的词法范围内,例如:
my $user;
{ # no autovivification is limited to this block
no autovivification;
$user = $data->{addon}{$site}{username} // "nothing";
}
//
就是defined-or operator,在这种情况下使用方便。
但对于像这样的简单问题,您可能会采用更简单的解决方案:
my $user;
if ( defined $data->{addon}{$site} ) {
$user = $data->{addon}{$site}{username} // "nothing";
}