通常情况下,我可以围绕哈希和数组的所有不同复杂性进行思考,但我似乎无法使其正常工作......
这是我的阵列:
$event['date'] = $my_date;
$event['machine'] = $my_machine;
这就是我希望我的哈希看起来像
$User{$name}{'allowed'} = 52;
$User{$name}{'denied'} = 4;
$User{$name}{'events'}[] = @event;
我需要遍历每个用户(当前有效),然后在该用户循环中完成每个事件。
2个问题:
任何帮助都将不胜感激。
答案 0 :(得分:3)
Perl中的数组具有以下属性:
0
开始。$array[0] = $val
。另一方面,哈希具有属性
$hash{"some key"} = $val
。如果密钥是有效标识符,则引号是可选的:$hash{some_key} = $val
。散列和数组都不是标量,但您可以使用一元\
运算符作为参考,然后是标量。
不要使用名称为“associative array”的其他语言混淆Perl调用哈希值,或者使用相同的哈希值和数组语法。
对于您的事件数据结构,您还需要一个哈希:
my %event = (
date => $my_date,
machine => $my_machine,
);
...;
$User{$name}{events} = \%event; # see the reference operator.
如果您希望用户拥有多个事件,您希望将该条目用作数组引用,并将\%event
推送到结尾:
push @{ $User{$name}{events} }, \%event;
@{ ... }
接受数组引用,取消引用它到数组。
给定一个哈希,你可以循环遍历
这样的键for my $key (keys %hash) { ... }
给定hashref,我们必须首先取消引用它:
for my $key (keys %{ code_producing_hashref() }) { ... }
给定数组引用,我们必须在循环之前取消引用它:
for my $value (@{ code_producing_arrayref() }) { ... }
例如,为了循环每个事件,我们可以做
for my $user (keys %User) {
say "User $user has the following events:";
for my $event (@{ $User{$user}{events} }) {
say "date=$event->{date} machine=$event->{machine}";
}
}
$hashref->{$key}
语法访问hashref中的字段。它的作用类似于my %hash = %$hashref; $hash{$key}
,除非没有不必要的副本。
Perl引用可能令人困惑,而且语法非常丑陋。我建议您阅读文档以便更好地理解:
答案 1 :(得分:3)
我不知道我是否完全正确。
你所描述的"我的阵列"看起来更像是散列%event
,因为你使用的是名字,而不是indizes。因此,让我们假设以下内容。
您有事件,每个事件都是哈希%event
,定义如下:
my %event;
$event{date} = $my_date;
$event{machine} = $my_machine;
请注意,您可以省略简单哈希键上的引号。现在,如果您已定义了多个类似事件,请说出%event1
,%event2
等等,则将它们添加到数组中。您必须添加对这些事件哈希的引用!
my @events = ( \%event1, \%event2 );
现在,您的用户哈希事件应该定义为:
$user{$name}{events} = [ @events ];
此处,您需要将用户的事件设置为对数组的引用。内容将是您的事件列表包含的内容。这基本上会将@events
的元素复制到您的用户对象中。您也可以像
$user{$name}{events} = \@events;
但是你直接引用了@events
数组。
现在循环很容易。
foreach my $name (@names) {
foreach my $event (@{$user{$name}{events}}) {
# do something with $event
}
}
我使用@{ ... }
取消引用events-array,以获取$event
中的简单事件列表。
答案 2 :(得分:0)
构建抽象以添加事件。
sub add_event {
my($user,$name,$event) = @_;
push @{ $user->{$name}{events} }, $event;
}
在实践中,对它的调用类似于
add_event \%User, "MasterZ", { date => $^T, machine => "host1" };
另一种抽象也会对此有所帮助。
use Storable qw/ dclone /;
sub all_events {
my($user,$name) = @_;
my $clone = dclone $user->{$name}{events};
wantarray ? @$clone : $clone;
}
对dclone
的调用执行deep copy,这使得返回值可以安全地传递给局外人,而不用担心他们会修改您的内部数据。
在
中使用它foreach my $event (all_events $name) {
# do stuff with $event->{date} and $event->{machine}
}
使用以下代码
#! /usr/bin/env perl
use strict;
use warnings;
use Storable qw/ dclone /;
sub add_event {
my($user,$name,$event) = @_;
push @{ $user->{$name}{events} }, $event;
}
sub all_events {
my($user,$name) = @_;
my $clone = dclone $user->{$name}{events};
wantarray ? @$clone : $clone;
}
my %User = ( MasterZ => { allowed => 52, denied => 4 } );
add_event \%User, "MasterZ", { date => $^T, machine => "host1" };
add_event \%User, "MasterZ", { date => $^T + 1, machine => "host2" };
for (all_events \%User, "MasterZ") {
my($date,$machine) = @{$_}{qw/ date machine /};
print "$date - $machine\n";
}
# show the internal layout of %User
use Data::Dumper;
$Data::Dumper::Indent = $Data::Dumper::Terse = 1;
print Dumper \%User;
输出类似于
1371671154 - host1 1371671155 - host2 { 'MasterZ' => { 'allowed' => 52, 'events' => [ { 'date' => '1371671154', 'machine' => 'host1' }, { 'date' => 1371671155, 'machine' => 'host2' } ], 'denied' => 4 } }