0

我有一个巨大的、巨大的、巨大的数据结构,其格式与 Data::Dumper 的格式完全相同(尽管为了解释问题而进行了极大的简化)。

{
  Fred => {
            "Street Name" => ["First Avenue"],
            "animal" => ["lion", "snake", "spider", "monkey"],
          },
  Dave => {
            "Street Name" => ["Church Street"],
            "animal" => ["dog", "cat", "pig", "elephant"],
          },
}

我在尝试从这个哈希结构的更下方访问数据时遇到了真正的问题,我之前已经做过多次,但由于某种原因它在这种情况下不起作用。

访问此哈希结构中的每个元素并打印结构的每个级别的正确方法是什么?例如

   foreach my $key ( keys %hashStructure ) {
          print "$key";
          foreach my $key2 ...
4

2 回答 2

4

这是你的结构:

{
  Fred => {
            "Street Name" => ["First Avenue"],
            "animal" => ["lion", "snake", "spider", "monkey"],
          },
  Dave => {
            "Street Name" => ["Church Street"],
            "animal" => ["dog", "cat", "pig", "elephant"],
          },
}

让我们一次把它拆开一个层次。这里分为三个层次:

外层代表我将调用的散列%person_hash。您的哈希中有两个键:FredDave. 这两个散列值中的每一个都指向(参考)其他散列值。那是$person_hash{Dave}一个哈希引用$person_hash{Fred}是一个哈希引用

要将这两个哈希引用转换为哈希,我使用解引用语法:

%attribute_hash = %{ $person_hash{Dave} };

现在,我们有一个名为%attribute_hash. 这%attribute_hash包含 Fred 和 Dave 的属性。在您的示例中,每个%attribute_hash散列中有两个元素(请记住:Dave 一个,Fred 一个)。这些%attribute_hash哈希中的两个键控元素包含“街道地址”和“动物”。

要访问列表,我可以使用取消引用语法:@values = @{ $attribute_hash{$attribute} }.

那么,让我们看看如何打印所有这些:

use strict;
use warnings;
use feature qw(say);

my %person_hash = (
    Fred => {
        "Street Name" => [ "First Avenue" ],
        animal => [ "lion", "snake", "spider", "monkey" ],
    },
    Dave => {
        "Street name" => [ "Church Street" ],
            animal =>  [ "dog", "cat", "pig", "elephant" ],
    },
);

# The first level contains the keys `Dave` and `Fred`
for my $person ( keys %person_hash ) {
    say "The person is $person";

    # The keys will be for "Dave" and "Fred", and will be the value
    # of $person. This is a hash reference, so let's dereference it.
    my %attribute_hash = %{ $person_hash{$person} };

    # We have a hash of attributes beloning to that person. The
    # attributes will be "Street Name" and "animal"
    for my $attribute ( keys %attribute_hash ) {
        say "    ${person}'s attribute is '$attribute'";

        # Each "attribute" points to a list. Let's get the list
        my @value_list = @{ $attribute_hash{$attribute} };

        # Now we can go through that list:
        for my $value ( @value_list ) {
            say "        ${person}'s attribute '$attribute' has a value of $value";
        }
    }
}

这打印出来:

The person is Dave
    Dave's attribute is 'Street name'
        Dave's attribute 'Street name' has a value of Church Street
    Dave's attribute is 'animal'
        Dave's attribute 'animal' has a value of dog
        Dave's attribute 'animal' has a value of cat
        Dave's attribute 'animal' has a value of pig
        Dave's attribute 'animal' has a value of elephant
The person is Fred
    Fred's attribute is 'Street Name'
        Fred's attribute 'Street Name' has a value of First Avenue
    Fred's attribute is 'animal'
        Fred's attribute 'animal' has a value of lion
        Fred's attribute 'animal' has a value of snake
        Fred's attribute 'animal' has a value of spider
        Fred's attribute 'animal' has a value of monkey

->您还应该知道,我可以使用以下语法直接访问其中的值:

say "Fred's first animal in his list is " . $person_hash{Fred}->{animal}->[0];

当我取消引用时,我也可以使用该语法:

say "Fred's animals are " . join ", ", @{ $person_hash->{Fred}->{animal} };

请注意,这$person_hash->{Fred}->{animal}是对包含动物的数组的引用。

于 2014-06-13T19:25:25.627 回答
1

您只需要考虑每个级别的数据是什么。使用 Person 类封装这些似乎是关于一个人的数据可能是值得的,这将大大简化您打印出这些值的代码。

#!/usr/bin/perl

use strict;
use warnings;

my %hash =  (
   'Fred' => {
      'Street Name' => ['First Avenue'],
      'animal'      => ['lion','snake','spider','monkey',]
   },
   'Dave' => {
      'Street Name' => ['Church Street'],
      'animal' => ['dog','cat','pig','elephant',]
   }
);

foreach my $namekey ( keys %hash ) {
   print "Name: $namekey\n";
   foreach my $key ( keys %{$hash{$namekey}} ) {
      print "$key: " .
         join(',', @{$hash{$namekey}{$key}}) . "\n";
   }
}

__END__ # outputName: Dave
animal: dog,cat,pig,elephant
Street Name: Church Street
Name: Fred
Street Name: First Avenue
animal: lion,snake,spider,monkey

人物示例:

package Person; 

sub new {
   my ($class, %args) = @_; 

   bless \%args, $class;
}

sub name {
   my $self = shift;

   return $self->{name};
}

sub street_name {
   my $self = shift;

   return $self->{'Street Name'};
}

sub animal {
   my $self = shift; 

   return $self->{animal};
}

sub as_string {
   my $self = shift;

   return join("\n", 
      $self->name, 
      join(',', @{$self->street_name}),
      join(',', @{$self->animal})
   );
}

1;

my $fred = Person->new(
   name          => 'Fred',
   'Street Name' => ['First Avenue'],
   animal        => ['lion','snake','spider','monkey',]
);
print $fred->as_string . "\n";

__END__ # output
Fred
First Avenue
lion,snake,spider,monkey
于 2014-06-13T14:50:07.920 回答