按顺序遍历哈希成员

问题描述 投票:0回答:2

我如何订购一个类的哈希成员?我的课看起来像这样

    package TestSuiteInterface {

    use Tie::IxHash;

    sub new {
        my ($class, $name) = @_;
        my $self = {};
        my %schedulerdata = {};
        tie(%schedulerdata, 'Tie::IxHash');
        $self->{name} = $name;
        $self->{scheduler} = %schedulerdata;
        bless $self, $class;
        return $self;                                                                                                                                                                                                                        
    }
    sub getVariables {
        my ($self) = shift;
        return $self->{variables}
    }
    sub loadtests {
        my ($self) = shift;
        {
            #tie(my %data, 'Tie::IxHash');                                                                                                                                                                                                   
            #%data = %{$self->{scheduler}};                                                                                                                                                                                                  
            my @scheduler = values %{$self->{scheduler}};
            #die "oops" unless $self->{scheduler}                                                                                                                                                                                            
            $_->() for (@scheduler);
            return 1;
        }
        return 0;
    }
}

以上,我尝试使用Tie :: IxHash。我试图弄清楚如何为$ self-> {scheduler}做到这一点,稍后子类将添加项。例如

package Test {
    use base 'TestSuiteInterface';
    use main_common;
    sub new {
        my ($class, $name) = @_;
        my $self = {};
        class->SUPER::new($name);
        $self->{variables}={};
        $self->{scheduler} = {
            boot_linuxrc => sub{ loadtest("boot/boot_linuxrc"); },
            first_boot => sub{ loadtest("installation/first_boot");}
        };
        bless $self, $class;
        return $self;
    }
}

要使用Tie :: IxHash,我必须在设置变量之前使用它,对吗?因此,最后在负载测试中使用它是没有用的。我可以在构造函数中执行此操作,还是可以在循环内按顺序取回$ self-> {scheduler}?

perl oop hash
2个回答
4
投票

new()方法中,创建一个Tie :: IxHash对象并将其存储在测试对象中。

my %schedulerdata = {};
tie(%schedulerdata, 'Tie::IxHash');
...
$self->{scheduler} = %schedulerdata;

实际上,那里有一些小错误。首先,您使用哈希引用初始化哈希。

my %schedulerdata = {};

真的,您想使用一个空列表初始化它:

my %schedulerdata = ();

或者,更好的是,仅依靠Perl将其初始化为空哈希。

my %schedulerdata;

然后,您尝试将哈希存储在对象中。但是对象属性只能是标量,因此您需要在对象中存储对哈希的引用。

$self->{scheduler} = \%schedulerdata;

将所有内容放在一起,构造函数方法应如下所示:

sub new {
    my ($class, $name) = @_;
    my $self = {};
    my %schedulerdata;
    tie(%schedulerdata, 'Tie::IxHash');
    $self->{name} = $name;
    $self->{scheduler} = \%schedulerdata;
    bless $self, $class;
    return $self;
}

但是这些问题并不是导致此问题不起作用的原因。稍后,当您为调度程序提供值时。您的代码如下所示:

$self->{scheduler} = {
    boot_linuxrc => sub{ loadtest("boot/boot_linuxrc"); },
    first_boot   => sub{ loadtest("installation/first_boot"); }
};

但是想想这是怎么回事。您正在创建一个全新的匿名哈希,并将对该哈希的引用存储在对象中。这将覆盖您精心构造的绑定哈希,然后将其替换为标准(非绑定)哈希。

为了保留哈希的束缚特性,您需要向其添加键/值对-而不是完全覆盖它。我认为这样的代码会起作用。

$self->{scheduler}->{boot_linuxrc} = sub{ loadtest("boot/boot_linuxrc"); };
$self->{scheduler}->{first_boot}   = sub{ loadtest("installation/first_boot"); };

注意:如果您的代码包含use warnings(Perl代码应始终包含[​​C0]),则该行:

use warnings

将触发警告:

参考找到期望的大小均匀的列表

这就是为什么我们总是建议包括my %schedulerdata = {}; :-)


0
投票

最后,我的解决方案是不使用Tie :: IxHash。相反,我使用了一个单独的函数来获取有序列表,并将其分配给实例成员。我将以另一种方式发布它,因为@Dave Cross的解决方案仍然是正确的。

use warnings

@ list现在包含4个元素。 [boot_linuxrc,sub {loadtest(“ boot / boot_linuxrc”)},first_boot,sub {loadtest(“ installation / first_boot”)}]。在示例中,set_scheduler使用map使用@list的索引[1]和[3]为我提供了一个子列表。 0 ..(@list / 2)-1是在@order中获得正确的大小(2个项目)。

我用使用以下项的代码波纹管替换了[[package Test中的以前的$ self-> {scheduler}] >>sub set_scheduler {  my ($self, @list) = @_;  # get a list of the subroutines of the hash  my @order = map { $list[($_ * 2) + 1] } 0 .. (@list / 2) - 1;  my %schedule = @list;  $self->{scheduler} = \%schedule;  $self->{scheduler_order} = \@order;  return $self;  }

然后,我在负载测试中运行以下命令

$self->set_scheduler( boot_linuxrc => sub { loadtest("boot/boot_linuxrc") }, installer_extended => sub { loadtest("installation/first_boot") } );

感谢@DaveCross
© www.soinside.com 2019 - 2024. All rights reserved.