Ken Ingram
Ken Ingram

Reputation: 1608

Perl: How to print array of hashes,

There don't seem to be a lot of examples of people using arrays containing hashes. I want to check the array I am constructing in a sub but I'm having some issues accessing the structure. Perhaps I am not imagining the construct the way it exists. This is an example of some code:

#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;


my (%data, %data2, @holding);

%data = (
    'monday' => "This stuff!",
    'tuesday' => "That stuff!!",
    'wed' => "Some other stuff!!!"
    );

push @holding, %data;

%data2 = (
    'monday' => "Yet more stuff... :-P ",
    'tuesday' => "Some totally different stuff!",
    'wed' => "What stuff is this?"
    );

push @holding, %data2;

foreach my $rows(@holding){
    foreach my $stuff (keys %{$holding[$rows]} ){
        print "$holding[$rows]{$stuff}\n";  
    }
}

The error message I get:

Argument "wed" isn't numeric in array element at /home/kingram/bin/test line 27.
Can't use string ("wed") as a HASH ref while "strict refs" in use at /home/kingram/bin/test line 27.

My work with arrays in perl is not extensive so I'm sure I'm missing something basic.

When I use Dumper I am expecting VAR1 and VAR2 expressing two distinct rows but I get

$ ~/bin/test
$VAR1 = [
          'wed',
          'Some other stuff!!!',
          'monday',
          'This stuff!',
          'tuesday',
          'That stuff!!',
          'wed',
          'What stuff is this?',
          'monday',
          'Yet more stuff... :-P ',
          'tuesday',
          'Some totally different stuff!'
        ];

Upvotes: 1

Views: 5972

Answers (2)

Dave Cross
Dave Cross

Reputation: 69314

Even when you get the data structure right, this code is still not going to work:

foreach my $rows(@holding){
    foreach my $stuff (keys %{$holding[$rows]} ){
        print "$holding[$rows]{$stuff}\n";  
    }
}

When you use foreach my $rows (@holding) to iterate over your array, each time round the loop $rows will contain an element from the array, not the index of an element. So you don't need to look it up with $holding[$rows]. You code should look like this:

foreach my $rows (@holding){
    foreach my $stuff (keys %{$rows} ){
        # $rows will contain a hash *reference*.
        # Therefore use -> to access values.
        print "$rows->{$stuff}\n";  
    }
}

Upvotes: 2

simbabque
simbabque

Reputation: 54381

You need to work with references. If you push a hash into an array, it's just a flat list. You're using the right dereference operators in your loop, but you're missing a backslash \ when pushing.

push @holding, \%data;

The backslash \ gives you a reference to %data, which is a scalar value. That will be pushed into your array.

See perlreftut for an explanation.


If you look at @holding after your two push operations, it's obvious what happens.

use Data::Printer;
p @holding;

__END__
[
    [0]  "monday",
    [1]  "This stuff!",
    [2]  "tuesday",
    [3]  "That stuff!!",
    [4]  "wed",
    [5]  "Some other stuff!!!",
    [6]  "wed",
    [7]  "What stuff is this?",
    [8]  "monday",
    [9]  "Yet more stuff... :-P ",
    [10] "tuesday",
    [11] "Some totally different stuff!"
]

Upvotes: 6

Related Questions