Perl - 在哈希结构中打印元素

时间:2014-06-13 14:42:02

标签: perl hash hashtable hash-of-hashes data-dumper

我遇到了一个问题,我希望有人可以提供帮助...

我有一个巨大的,巨大的,庞大的数据结构,完全采用Data :: Dumper下面显示的格式(虽然为了解释问题而大大简化了)。

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

我在尝试从这个哈希结构中进一步访问数据时遇到了实际问题,这是我之前多次做过的事情,但是由于某些原因它在这个实例中不起作用。

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

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

非常感谢您对此的帮助,谢谢

2 个答案:

答案 0 :(得分:4)

这是你的结构:

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

让我们一次分开一个级别。这里有三个级别:

外层代表哈希I' ll %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}是包含动物的数组的引用

答案 1 :(得分: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