我有一个问题,我希望有人可以提供帮助(为了解释我的问题而简化)。
我有以下哈希的数组哈希(我认为这是什么呢?)
{
Cat => {
Height => ["Tiny"],
},
Dog => {
Colour => ["Black"],
Height => ["Tall"],
Weight => ["Fat", "Huge"],
},
Elephant => {
Colour => ["Grey"],
Height => ["Really Big"],
Weight => ["Fat", "Medium", "Thin"],
},
}
下面的程序将打印整个数据结构。 我想用这种方式来做这件事
my %h;
for my $animal (keys %h) {
print "$animal\n";
for my $attribute ( keys %{$h{$animal}} ) {
print "\t $attribute\n";
for my $i (0 .. $#{$h{$animal}{$attribute}} ) {
print "\t\t$h{$animal}{$attribute}[$i]\n";
}
}
}
我正在尝试访问数据结构的特定部分。例如,我只想打印每个动物的Height
数组,因为我不关心此示例中的其他Colour
,Weight
属性。
我确信这有一个简单的答案,我知道我需要指定Height
部分,但这样做的正确方法是什么?我尝试了多种方法,我认为这种方法没有成功。
答案 0 :(得分:2)
在您的代码中,而不是使用
循环所有属性for my $attribute ( keys %{ $h{$animal} } ) { ... }
只需使用您感兴趣的那个。就像这样
for my $animal (keys %h) {
print "$animal\n";
for my $attribute ( 'Height' ) {
print "\t $attribute\n";
for my $i (0 .. $#{$h{$animal}{$attribute}} ) {
print "\t$h{$animal}{$attribute}[$i]\n";
}
}
}
我会选择循环高度数组的内容而不是索引,使代码看起来像这样:
for my $animal (keys %h) {
print "$animal\n";
print "\t\t$_\n" for @{ $h{$animal}{Height} };
}
答案 1 :(得分:2)
快速浏览一下您的数据结构:这是哈希 数组 的哈希值!哇。心灵正在爆炸。
这是打印出所有数据的快捷方法:
use feature qw(say);
# Working with a Hash of Hash of Arrays
for my $animal (keys %h) {
say "Animal: $animal";
# Dereference: Now I am talking about a hash of arrays
my %animal_attributes = %{ $h{$animal} };
for my $attribute (keys %animal_attributes) {
# Dereference: Now I am talking about just an array
my @attribute_value_list = @{ $animal_attributes{$attribute} };
say "\tAttribute: $attribute - " . join ", ", @attribute_value_list;
}
}
注意我使用解除引用。我没有 有 来进行取消引用,但它使代码更容易使用。我不必考虑我的各种水平。我知道我的动物是 hash 属性,这些属性是属性值的数组。通过使用解除引用,它可以让我保持正确。
现在,假设您只打印出所需属性列表。您可以使用exists
函数在尝试打印之前查看该属性是否存在。
use feature qw(say);
use constant DESIRED_ATTRIBUTES => qw(weight height sex_appeal);
# Working with a Hash of Hash of Arrays
for my $animal (keys %h) {
say "Animal: $animal";
# Dereference: Now I am talking about a hash of arrays
my %animal_attributes = %{ $h{$animal} };
for my $attribute ( DESIRED_ATTRIBUTES ) {
if ( exists $animal_attributes{$attribute} ) {
# Dereference: Now I am talking about just an array
my @attribute_value_list = @{ $animal_attributes{$attribute} };
say "\tAttribute: $attribute - " . join ", ", @attribute_value_list;
}
}
}
相同的代码,我刚刚添加了一个if子句。
当您进入这些复杂的数据结构时,最好使用面向对象的设计。 Perl在OOP Perl上有一个excellent tutorial。如果你使用它,你可以定义一类动物,并有各种方法来提取你想要的数据。它使维护变得更加容易,并且您可以勇敢地创建更复杂的数据结构,而无需担心跟踪您的位置。
答案 2 :(得分:1)
假设您的变量名为%h:
foreach my $animal (keys %h) {
my $heights = $h{$animal}->{Height}; #gets the Height array
print $animal, "\n";
foreach my $height( @$heights ) {
print " ", $height, "\n";
}
}
答案 3 :(得分:1)
我认为有时直接使用该值会更容易,如果它是对另一个结构的引用。你可以这样做:
my $height = "Height";
while (my ($animal, $attr) = each %h) {
print "$animal\n";
print "\t$height\n";
print "\t\t$_\n" for @{ $attr->{$height} };
}
使用主键的值,您可以跳过一步的引用并直接进入Height
属性。下面的输出符合原始代码中的格式。
<强>输出:强>
Elephant
Height
Really Big
Cat
Height
Tiny
Dog
Height
Tall
答案 4 :(得分:0)
我想我已经解决了,发现我做错了什么?
我认为这应该是:
my %h;
for my $animal (keys %h) {
print "$animal\n";
for my $i (0 .. $#{$h{$animal}{Height}} ) {
print "\t\t$h{$animal}{Height}[$i]\n";
}
}