murtu_4u has asked for the wisdom of the Perl Monks concerning the following question:

Hi. my problem is simple but i couldnt find the answer since im a newbie. I have created a hash of hashes. Something like this.
%a = {} ; $a{"KEY1"}->{"VALUE1"}->{key} = value11 ; $a{"KEY1"}->{"VALUE2"}->{key} = value21 ; $a{"KEY2"}->{"VALUE1"}->{key} = value11 ; $a{"KEY2"}->{"VALUE2"}->{key} = value21 ;

So u see, there is a hash, whose keys have values that each point to another hash. Basically im storing some network data which is initially indexed by the source MAC address and for each source MAC address i have several destination MAC addresses. and then for each of these source destination pairs i have some key value pairs like numBytesTransferred, numRetries etc.

The problem
------------
1. foreach $source (keys %allData) 2. { 3. foreach $dest ( keys $allData{$source} ) 4. { 5. #access the values 6. } 7. }

Line 3 has an error that says "Type of arg 1 to keys must be hash (not hash element) at file.pl.."

Please help ! or suggest some alternative better way to organize the data that I have talked abt above. Thanks in advance.

MJ

Replies are listed 'Best First'.
Re: Simple Anon Hash Query
by davido (Cardinal) on Jan 21, 2007 at 07:13 UTC

    keys needs a hash, not a hashref. You have to dereference the hashref to be left with a first-class hash:

    foreach my $source ( keys %allData ) { foreach my $dest ( keys %{ $allData{$source} } ) { # access the values } }

    See also perlref, perlreftut, and perldsc.


    Dave

Re: Simple Anon Hash Query
by graff (Chancellor) on Jan 21, 2007 at 08:19 UTC
    In addition to what davido said, don't use curlies to initialize a hash. Your first line ( %a = {};) should be:
    %hash = ();
    (%a doesn't really conflict with the $a that is used by the sort function, but why create a chance for confusion?)

    Curlies are used like that when initializing a reference to a hash:

    my $hashref = {}; $$hashref{level1_key}{level2_key}{level3_key} = "value"; ... for my $key1 ( keys %$hashref ) { for my $key2 ( keys %{$$hasref{$key1}} ) { for my $key3 ( keys %{$$hasref{$key1}{$key2}} ) { # do something with $$hashref{$key1}{$key2}{$key3} } } }
Re: Simple Anon Hash Query
by rodion (Chaplain) on Jan 21, 2007 at 12:57 UTC
    Also note that your third level key in the example is the literal word "key". Perl puts quotes around "bare words" that are in the position of hash keys. If you mean't this as a variable (it's lower case, unlike the other keys), then you need a dollar sign before it. This is an easy mistake to make when you're a newbie coming from another language. (Also, don't start relying on bare word keys, since this feature will probably go away in Perl6.)
Re: Simple Anon Hash Query
by logie17 (Friar) on Jan 21, 2007 at 21:56 UTC
    If you're going to be using a referenced hash then the following code will do the trick for you. It gets a little confusing when to use {} and when to use (), at least I would always get these mixed up.
    #! /usr/local/bin/perl use warnings; use strict; my $allData = { src1 => { dest1 => '112.112.112.112', dest2 => '112.112.112.113' }, src2 => { dest1 => '192.168.1.101', dest2 => '192.167.1.102' } }; foreach my $source ( keys %{$allData}){ foreach my $dest (keys %{$allData->{$source}}){ #blah } }

    Hope that makes sense or helps.
    Cheers!
    s;;5776?12321=10609$d=9409:12100$xx;;s;(\d*);push @_,$1;eg;map{print chr(sqrt($_))."\n"} @_;
      Thank you all ! That had solved the problem