面向对象的perl,设置哈希值

时间:2016-10-17 23:11:05

标签: perl class oop hash

我有一个班级:

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''?

1 个答案:

答案 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;
}

请注意,有更简洁的方法可以处理键/值列表。