Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations bkrike on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Totally confused over hash behaviour 1

Status
Not open for further replies.

1DMF

Programmer
Jan 18, 2005
8,795
GB
Hi, I have created an array of hashes like so...
Code:
    # Get user details
    my @user = &getSQL("Users","UserID,Role,FullName","1=1","UserID ASC");
       
    foreach my $user (@user)
    {
        $USERS[0]->{$user->{'UserID'}} = $user->{'FullName'};
        $USERS[1]->{$user->{'UserID'}} = $user->{'Role'};
    }

All seem fine so far, however, when i try to access the hashes later on with ....
Code:
    foreach (@USERS) {
        foreach my $key (keys $_){
            print "key = $key , value = " . $_->{$key} . "<br>";
        }
    }

I get....
Type of arg 1 to keys must be hash (not scalar dereference)

yet if I do this...
Code:
   print "users[0] = " . $USERS[0];

I get ....
users[0] = HASH(0x2c35044)

So I don't get it , it is hash isn't so why won't the foreach work?

cheers,
1DMF

"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you."

"If a shortcut was meant to be easy, it wouldn't be a shortcut, it would be the way!"

Google Rank Extractor -> Perl beta with FusionCharts
 
I suspect you want something like this:

Code:
foreach my $user (@USERS) {
    foreach my $key (keys %{$USERS[$user]}){
        print "key = $key , value = " . $USERS[$user]->{$key} . "<br>";
    }
}
I didn't test it, but that looks about right.
 
An array can't contain "hashes", it can contain hash REFERENCES.

Thus, you need to put %{ } around an array element that is a hashref to dereference it as a hash.

Kirsle.net | My personal homepage
Code:
perl -e '$|=$i=1;print" oo\n<|>\n_|_";x:sleep$|;print"\b",$i++%2?"/":"_";goto x;'
 
Perl:
use Data::Dumper;
# Get user details
    my @user = &getSQL("Users","UserID,Role,FullName","1=1","UserID ASC");

print Dumper(@user);
will give you a graphic representation of the structure; from there you should be able to figure out how to dereference it to do what you want.


Steve

[small]"Every program can be reduced by one instruction, and every program has at least one bug. Therefore, any program can be reduced to one instruction which doesn't work." (Object::perlDesignPatterns)[/small]
 
Thus, you need to put %{ } around an array element that is a hashref to dereference it as a hash.

I don't understand, I don't always need to do this....
Code:
my @rs = &getSQL("Contacts","Title,FirstName,LastName,CompanyName,[Membership Date]","(DATEADD(day,45,[Membership Date]) >= GETDATE()) AND ContactTypeID = 'Member' AND (MembershipLevel = 'Adviser' OR MembershipLevel = 'Trainee')","[Membership Date] DESC");

my $i=0;

for(@rs){
    $i++;
    #format date
    $_->{'Membership Date'} = substr($_->{'Membership Date'},0,10);
    my @dte = split(/-/,$_->{'Membership Date'});
    $_->{'Membership Date'} = "$dte[2]/$dte[1]/$dte[0]";
    $_->{'ID'} = $i;
    $_->{'FirstName'} =~ s/'/\\'/g;
    $_->{'LastName'} =~ s/'/\\'/g;
    $_->{'CompanyName'} =~ s/'/\\'/g;
}

I can write that where @rs is an array of hashes without having to use a percent sign anywhere.

I can't get my head round when a dereference is required as it doesn't always seem to require one?

"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you."

"If a shortcut was meant to be easy, it wouldn't be a shortcut, it would be the way!"

Google Rank Extractor -> Perl beta with FusionCharts
 
well if I uses data::dumper on @USERS i get..
$VAR1 = { 'Christopher' => 'Christopher Smith', 'Craig' => 'Craig Jones' }; $VAR2 = { 'Christopher' => 'Admin', 'Craig' => 'Admin' };
which is exactly what I expect to see and array of hashes.

So what's the problem with my foreach and hash:keys command?

I'm lost over all this, if I loop and array of hashes normally I don't need %{} wrapped around $_ ,

"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you."

"If a shortcut was meant to be easy, it wouldn't be a shortcut, it would be the way!"

Google Rank Extractor -> Perl beta with FusionCharts
 
oh well if i wrap $_ in %{}, it works fine....
Code:
foreach (@USERS) {        
    foreach my $key (keys %{$_}){            
        print "key = $key , value = " . $_->{$key} . "<br>";        
    }    
}

So got there in the end.

Bit unsure why $_->{'hash key'} works, but keys $_ doesn't.

does '->' dereference first automatically ?

"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you."

"If a shortcut was meant to be easy, it wouldn't be a shortcut, it would be the way!"

Google Rank Extractor -> Perl beta with FusionCharts
 
When you do a foreach keys on a hash, you always use the % sign, like "foreach (keys %myhash)", not the $ sign like when you actually get a key from it, $myhash{key}.

Same for @, foreach (@array), not foreach($array)

So when you use a reference in either context you need to dereference it with %{} or @{}.

Kirsle.net | My personal homepage
Code:
perl -e '$|=$i=1;print" oo\n<|>\n_|_";x:sleep$|;print"\b",$i++%2?"/":"_";goto x;'
 
As for Data::Dumper, the difference between this

Code:
print Dumper(@array);
print Dumper(@arrayref);

is that the output is this for regular array:

Code:
$VAR1 = "dog";
$VAR2 = "cat";
$VAR3 = "mouse";

and this for an array reference:

Code:
$VAR1 = [
   "dog",
   "cat",
   "mouse",
];

Kirsle.net | My personal homepage
Code:
perl -e '$|=$i=1;print" oo\n<|>\n_|_";x:sleep$|;print"\b",$i++%2?"/":"_";goto x;'
 
er,

-- print Dumper(@arrayref);
++ print Dumper($arrayref);

Kirsle.net | My personal homepage
Code:
perl -e '$|=$i=1;print" oo\n<|>\n_|_";x:sleep$|;print"\b",$i++%2?"/":"_";goto x;'
 
Thanks for clearing that up Kirsle

"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you."

"If a shortcut was meant to be easy, it wouldn't be a shortcut, it would be the way!"

Google Rank Extractor -> Perl beta with FusionCharts
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top