For Programmers: Free Programming Magazines  


Home > Archive > PERL Beginners > August 2007 > Accessing hash within an array of hashes









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Accessing hash within an array of hashes
Charles J Gillan

2007-08-07, 7:59 am


I have a problem with extracting an individual hash from an array of
hashes. I can't work out, or find elsewhere, the syntax for this.

Code as follows:

devices_array_oH is set up as array of hashes

I want to loop over all hashes in the array and to print the key value pairs for
each hash.

I have tried the following but get run-time errors:

my($num_devices, $idevice);

$num_devices = scalar (@devices_array_oH) ;

for ($idevice=0; $idevice < $num_devices; $idevice++)
{
my (%device_hash, $itemp, $key);

$itemp = $idevice + 1;

#
#--- Extract one element of array to local hash
#

%device_hash = $devices_array_oH[$idevice]; <----------- Flagged as run-time error:

Reference found where even size list expected

print " Details of device $itemp: ";
print "\n\n";

foreach $key (keys(%device_hash))
{
print (" $key \t $device_hash{$key} \n"); <---- Flagged as run-time error
} use ofun-initialized value in concatenation
Presumably due to above

print "\n\n";
print " ***** End of details for all devices ";
print "\n\n";
}

Just can't figure it out - any suggestions.

Thanks,

Charles.





Paul Lalli

2007-08-07, 7:59 am

On Aug 7, 7:59 am, c.gil...@ecit.qub.ac.uk (Charles J Gillan) wrote:
> I have a problem with extracting an individual hash from an array of
> hashes. I can't work out, or find elsewhere, the syntax for this.


The syntax is found in
perldoc perlref
perldoc perlreftut
perldoc perllol
and
perldoc perldsc


> Code as follows:
>
> devices_array_oH is set up as array of hashes


No. There is no such variable. Variables in Perl start with $, @, %,
&, or *. Perhaps '@devices_array_oH' is an array of hashes?

> I want to loop over all hashes in the array and to print the key value pairs for
> each hash.
>
> I have tried the following but get run-time errors:
>
> my($num_devices, $idevice);
>
> $num_devices = scalar (@devices_array_oH) ;
> for ($idevice=0; $idevice < $num_devices; $idevice++)


These two lines are almost certainly better written:

for my $idevice (0 .. $#devices_array_oH) {

> {
> my (%device_hash, $itemp, $key);
>
> $itemp = $idevice + 1;
>
> #
> #--- Extract one element of array to local hash
> #
>
> %device_hash = $devices_array_oH[$idevice];
> <----------- Flagged as run-time error:


No. Flagged as run-time warning. Very different.

> Reference found where even size list expected


And did you look up that warning message to see what it means?

perldoc perldiag
Reference found where even-sized list expected
(W misc) You gave a single reference where Perl was
expecting a list with an even number of elements (for
assignment to a hash).

So this is telling you that $devices_array_oH[$idevice] is a
reference, and you're trying to use it as a hash. You can't do that.
You can either assign that reference to a new scalar variable, or you
can dereference the reference and assign the resulting hash to a hash
variable:

my $device_hash_ref = $devices_array_oH[$idevice];
or
my %device_hash = %{$device_array_oH[$idevice]};

> print " Details of device $itemp: ";
> print "\n\n";
>
> foreach $key (keys(%device_hash))
> {
> print (" $key \t $device_hash{$key} \n");
> <---- Flagged as run-time error


Again. Warning. Not Error. Errors cause your program to stop.
Warnings are Perl's way of telling you "this is probably not what you
meant to do."

> use of un-initialized value in concatenation
> Presumably due to above


Yes. Because you created a hash that has only one key-value pair.
The key is the stringified-form of that reference, and its value is
undef.

> }
>
> print "\n\n";
> print " ***** End of details for all devices ";
> print "\n\n";
> }
>
> Just can't figure it out - any suggestions.


I would have written the program like this:

my $itemp = 1;
foreach my $device_hash_ref (@devices_array_oH) {

print " Details of device $itemp: ";
print "\n\n";

foreach my $key (keys %{$device_hash_ref})
{
print (" $key \t $device_hash{$key} \n");
}
$itemp++;
}

There is rarely a need to use C-style for loops, or to access arrays
via indices. Just use a foreach loop and get access to their contents
(in this case, the references to hashes) directly.

Your main issue, I believe, is thinking that arrays can contain
hashes. They cannot. They can only contain *references* to hashes.
Therefore, when you get an element of one of these arrays, you get a
reference to a hash, not an actual hash. That reference must be
dereferenced in order to use it.

Please, do read those perldocs I referred you to earlier.

Paul Lalli

Mr. Shawn H. Corey

2007-08-07, 7:59 am

Paul Lalli wrote:
> I would have written the program like this:
>
> my $itemp = 1;
> foreach my $device_hash_ref (@devices_array_oH) {
>
> print " Details of device $itemp: ";
> print "\n\n";
>
> foreach my $key (keys %{$device_hash_ref})
> {
> print (" $key \t $device_hash{$key} \n");


print (" $key \t $device_hash_ref->{$key} \n");

> }
> $itemp++;
> }
>



--
Just my 0.00000002 million dollars worth,
Shawn

"For the things we have to learn before we can do them, we learn by doing them."
Aristotle
Paul Lalli

2007-08-07, 7:00 pm

On Aug 7, 8:29 am, shawnhco...@magma.ca (Mr. Shawn H. Corey) wrote:
> Paul Lalli wrote:


> print (" $key \t $device_hash_ref->{$key} \n");


Whoops! Quite correct. Thanks for catching that, Shawn.

Paul Lalli

Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com