我有一个班级:
sub Importids {
my ($self, $id_ref) = @_;
foreach $id (@{$id_ref})
{
push(@{$self->{_ids}}, $id);
}
}
我将子程序传递给一个数组,然后说:
_device --> id1|
--> status --> 0/1
id2|
--> status --> 0/1
我还想在这个函数中添加我初始化哈希,但是我有一段时间这样做。 最后,我希望我的哈希对于许多ID看起来像这样:
sub Importids {
my ($self, $id_ref) = @_;
foreach $id (@{$id_ref})
{
push(@{$self->{_ids}}, $id);
}
foreach my $id_value(@{$self->{_ids}})
{
$self->{_devices}{$id_value}{'status'} = 0;
}
}
其中id是密钥。
我尝试在函数中执行以下操作:
for my $hash_key (keys %{$self->{_devices}})
{
print $self->{_devices}{$hash_key};
#print keys % {$self->_devices}};
}
但是当我按如下方式检查内容时,它只返回哈希的十六进制转储
HASH(0x....)
HASH(0x....)
...
...
HASH(0x....)
给出:
for my $hash_key (keys %{$self->{_devices}})
{
print $self->{_devices}->{$hash_key}->{'status'};
}
然而,当我尝试:
0
0
...
0
我得到了我想要的东西:
{{1}}
我应该如何访问密钥并添加其他字段,例如status2''?
答案 0 :(得分:3)
注意简短的第一部分是指原始问题,同时也发生了变化。
当您设置哈希时,使用$id_value
作为变量迭代具有id的数组。然后将其分配给不存在的键
$self->{_devices}{ids} = $id_value; # what is 'ids' string?
因此,将添加一个键'ids'
,每个分配都将覆盖前一个。另外,请注意这样$id_value
(将)成为值,而不是键,与问题所述相反。
$self->{_devices}
应该是什么?如果密钥是id,则要“初始化”,请说0
foreach my $id (@$id_ref)
{
push @{$self->{_ids}}, $id;
$self->{_devices}{$id} = 0;
}
有更紧凑和更清晰的方法,但我们首先澄清是否有这个意图。
更新以澄清评论
目标是构建一个结构
_device --> id1 --> status --> 0/1 id2 --> status --> 0/1 ...
我们还希望能够读取/更改值,并添加另一种“状态”。让我们首先忘记类并构建这个数据结构。 请参阅教程perlreftut和数据结构cookbook perldsc。
在Perl中,我们可以使用哈希引用,并使用进一步嵌套的哈希引用
my $hashref = {
'id1' => {
'status' => 0,
'status2' => 0
},
'id2' => {
'status' => 0,
'status2' => 0,
},
# ...
};
匿名哈希 { status => 0, status2 => 0 }
被指定为键'id1', 'id2'
的值。它通常被称为 hashref ,意思是对哈希的引用(严格来说是\%hash
)。 hashref是标量,单个值,因此可以将其分配给键。这就是我们使用 references 构建嵌套(复杂)数据结构的方法。它们很像指针。
我们可以在代码中填充它
use warnings 'all';
use strict;
use Data::Dumper; # to see our structures
my @ids = qw(id1 id2 id3);
my $hashref;
foreach my $id (@ids) {
foreach my $stat ('status', 'status2') {
$hashref->{$id}{$stat} = 0;
}
}
print Dumper($hashref);
密钥$id
一旦遇到就会添加到哈希( autovivified )。嵌套哈希(ref)中的键'status'
也是如此,它们被赋值0
。我们只需按
$hashref->{$id}{'status'} = 1;
print "$hashref->{$id}{'status'}\n";
我们可以用同样的方式添加另一个“状态”,$hashref->{$id}{'status3'} = 0
。
回到课堂上。我们只使用一个“状态”字段。请注意,没有错误检查已完成。
sub Importids
{
my ($self, $id_ref) = @_;
foreach my $id (@{$id_ref})
{
push @{$self->{_ids}}, $id;
$self->{_devices}{$id}{'status'} = 0;
}
return 1;
}
我们如何更改给定ID的值?我们先来介绍一下界面。使用$id
变量中的ID及其$val
中的新值,我们可以想象一个调用
$obj->status( { $id1 => $val1, $id2 => $val2 } );
# Or
$obj->status( $new_vals_for_ids_hashref );
这会在调用中构建一个hashref,或者使用之前构建的hashref。 然后这是一个方法
sub status
{
my ($self, $rhstat) = @_;
foreach my $id (keys %$rhstat) {
$self->{_devices}{$id} = $rhstat->{$id};
}
return 1;
}
如果新ID不存在,或者覆盖现有ID,则会添加新ID。 我们可以将这个相同的子也作为吸气剂 - 如果没有传递
sub status
{
my ($self, $rstat) = @_;
return $self->{_devices} if not defined $rstat;
foreach my $id (keys %$rstat) {
$self->{_devices}{$id} = $rstat->{$id};
}
return $self->{_devices};
}
预期用途my $devices = $obj->status();
。由于我们现在在一种情况下返回数据,因此在添加/更改ID时也会这样做,以保证接口的一致性。
您可以类似地添加“状态”字段,
$obj->add_status( [ qw(status2 status3) ] );
其中[ ... ]
是匿名数组,方法
sub add_status
{
my ($self, $rstats) = @_;
foreach my $stat (@$rstats)
{
foreach my $id (@{$self->{_ids}})
{
$self->{_devices}{$id}{$stat} = 0;
}
}
return 1;
}
请注意,有更简洁的方法可以处理键/值列表。