9

I have an Array of Hashes in a Hash that looks like this:

$VAR1 = {
          'file' => [
                      {
                        'pathname' => './out.log',
                        'size' => '51',
                        'name' => 'out.log',
                        'time' => '1345799296'
                      },
                      {
                        'pathname' => './test.pl',
                        'size' => '2431',
                        'name' => 'test.pl',
                        'time' => '1346080709'
                      },
                      {
                        'pathname' => './foo/bat.txt',
                        'size' => '24',
                        'name' => 'bat.txt',
                        'time' => '1345708287'
                      },
                      {
                        'pathname' => './foo/out.log',
                        'size' => '75',
                        'name' => 'out.log',
                        'time' => '1346063384'
                      }
                    ]
        };

How can I iterate through these "file entries" in a loop and access its values? Is it easier to copy my @array = @{ $filelist{file} }; so i only have an array of hashes?

0

2 Answers 2

24

No need to copy:

foreach my $file (@{ $filelist{file} }) {
  print "path: $file->{pathname}; size: $file->{size}; ...\n";
}
Sign up to request clarification or add additional context in comments.

3 Comments

just for info, if you got your hash with xml::simple xmlin you have to use foreach my $file (@{ $filelist->{file} })
Where is $filelist defined?
I had to use ... (@{ $filelist->{file} }) { for it to work. Ie dereference "->".
4

There are no arrays of hashes in Perl, only arrays of scalars. It only happens that there's a bunch of syntactic sugar in case those scalars are references to arrays or hashes.

In your example, $VAR1 holds a reference to a hash containing a reference to an array containing references to hashes. Yeah, that's quite a lot of nesting to deal with. Plus, the outer hash seems kinda useless, since it contains only one value. So yes, I think giving the inner array a meaningful name would definitely make things clearer. It's not actually a "copy": only the reference is copied, not the contents. All of the following are equivalent:

my @files = $VAR1 -> {file} # dereferencing with the -> operator
my @files = ${$VAR1}{file}  # derefencing with the sigil{ref} syntax
my @files = $$VAR1{file}    # same as above with syntactic sugar

Note that when using the sigil{ref} syntax, the sigil obeys the same rules as usual: %{$ref} (or %$ref) is the hash referenced by $ref, but the element of %{$ref} for a given key is ${$ref}{key} (or $$ref{key}). The braces can contain arbitrary code returning a reference, while the short version can only be used when a scalar variable already holds the reference.

Once your array of references to hashes is in a variable, iterating over it is as easy as:

for (@files) {
    my %file = %$_;
    # do stuff with %file
}

See: http://perldoc.perl.org/perlref.html

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.