在下面的代码中,有多个职业,其值为零但未在哈希中定义。示例:%data
中未定义管道工,但我需要将$data{'Plumber'}
设置为零。可能有多个职业没有任何价值观。我用if-else做了这个,但是有更好的方法吗?
#!/usr/bin/perl
use Data::Dumper;
%data = ('Teacher' => 45, 'Doctor' => 40,'Driver' => '10');
if (exists($data{'Plumber'})) {
print "Number of doctor is $data{'Plumber'}\n";
}
else {
$data{'Plumber'} = 0;
print "Number of doctor is $data{'Plumber'}\n";
}
print Dumper \%data;
有没有办法将%data
的所有未定义值设置为零?
条件是 - 首先检查散列中的哪些值是未定义的,并将这些值设置为0,而不是全部。
请参阅下面我的实际代码:[3月30日编辑的问题' 17]
my %map = (
blk => 'Block',
hrd => 'Hard',
sft => 'Soft',
success => 'Success',
unk => 'Unknown',
);
my %report;
for ( `$stats` ) {
my ($val, $type) = split;
$report{$map{$type}} = $val;
}
\%report;
$_ //= 0 for values %report;
print Dumper \%report;
我无法为哈希%报告中的所有未分配值设置0,
根据下面的评论,我使用$_ //= 0 for values %report;
来实现这一点,但是当我映射两个哈希时,我感到困惑,因为我是Perl的初学者
仅供参考.. $stats
是一个查询,我用它来从日志和示例输出下面获取一些值。
10 blk
20 sft
50 success
任何想法如何处理这一点都将受到高度赞赏
答案 0 :(得分:2)
您可以使用默认值:
print "Plumber number: ", ($data{'Plumber'} || 0), "\n";
这将使用0而不是任何Perl的非真值,例如""
,0
,undef
。如果您有这样的值而不想使用0,请使用//
运算符而不是'||
。
答案 1 :(得分:2)
你可能已经习惯了像Ruby Hash.new(0)
这样的东西。 Perl有几个库来实现它,Hash::DefaultValue来自一个好作者。麻烦的是它们依赖于捆绑,Perl让对象像数据类型一样的奇怪方式,这种方式很慢且有警告。
//
运算符而不是逻辑或||
运算符。
my $value = $data{'Plumber'} // 0;
区别很微妙,但它可以保护您免受像""
这样的错误值被转换为0.相反,仅当$data{'Plumber'}
包含未定义的值时才会使用0默认值不存在。
其次,如果修复了一组键,则可以将所有值显式设置为0.再次,使用//=
的已定义或||=
版本。
for my $key (@keys) {
$data{$key} //= 0;
}
有一些封装此默认值的选项。最简单的是将你的哈希包装在一个小类中,为你做这个。
package MyStuff;
sub new {
my $class = shift;
my $self = shift;
return bless $self, $class;
}
sub get {
my $self = shift;
my $key = shift;
return $self->{$key} // 0;
}
则...
my $stuff = MyStuff->new(\%data);
my $val = $stuff->get("Plumber");
方法调用会产生额外的开销,用户必须适应对象界面,但它比搭售更快。
答案 2 :(得分:1)
您的用例允许使用North America
预设哈希的所有值。在0
:
my %report;
为什么会这样:
@report{values %map} = (0) x keys %map;
设置哈希值的多个值。 @report{...}
的值用作%map
的键。 %report
生成一个零列表。由于(0) x ...
运算符在其右侧需要标量,因此x
在标量上下文中执行并生成数字5.因此,keys %map
将填充其默认值,之后仅填充存在的值在你的%report
被覆盖。