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"],
          },
}

これを 1 レベルずつ分解してみましょう。ここには 3 つのレベルがあります。

外側のレベルは、私が呼び出すハッシュを表します%person_hash。ハッシュには と の 2 つのキーがFredありDaveます。これら 2 つのハッシュのそれぞれの値は、他のハッシュをポイント (参照) します。これは$person_hash{Dave}ハッシュ参照$person_hash{Fred}あり、ハッシュ参照です。

これら 2 つのハッシュ参照をハッシュに変換するには、逆参照構文を使用します。

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

これで、 というハッシュができました%attribute_hash。これ%attribute_hashには Fred と Dave の属性が含まれます。あなたの例では、これらのハッシュのそれぞれに 2 つの要素が%attribute_hashあります (覚えておいてください: Dave 用と Fred 用に 1 つずつあります)。これらの%attribute_hashハッシュの 2 つのキー付き要素には、「Street Address」と「animal」が含まれています。

リストにアクセスするには、逆参照構文を使用できます: @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 に答える