如何解决Perl检查嵌套哈希引用
我有以下代码:
#!/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' => {}
}
};
如您所见,检查是否在嵌套结构中定义了用户,实际上创建了一个空键。我的任务是如何在不定义键的情况下检查hashref。
解决方法
您正在绊倒“自动生存”。 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编译指示,可以轻松关闭部分代码中的自动生存。所以只需添加:
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所指出的,这是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";
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。