0

I am trying to access the values of a hash inside an array. Example:

@worte = {}; 

for my $i (0 .. 4){
    my (%wortObj) = (Index => $i, Text => "Text$i"); 
    print "$wortObj{Index} $wortObj{Text}\n"; 
    push @worte, %wortObj; 
}

foreach $wortObject (@worte){
    print "$wortObject{Index} $wortObject{Text}\n"; 
}

The first print statement works and creates correct output. I would like the second print statement to give the same output. But I am only getting a number of empty lines. What am I doing wrong?

2 Answers 2

1

Perl has a feature called context which is either absolutely brilliant or unbelievably annoying. It now happens that a hash variable used in list context evaluates to a flat list of keys and values, e.g. %hash = (Index => 1, Text => "Text1") might produce the list

'Text', 'Text1', 'Index', 1

Each of those items is then pushed onto the array. There is also scalar context which tells us how many “buckets” in the hash are being used. But how can we push the hash onto the array?

We don't. For certain reasons a collection can't have another collection as a value. Instead we must use a reference, which we can obtain with the \ operator (a reference is like a pointer, but safer). We can push that hash reference onto the array:

push @worte, \%wortObj;

Now when we loop over the items in that array, they aren't hashes – they are references to hashes. Therefore before accessing fields in the “hashref”, we have to dereference them first. One way to do that is to use the -> operator, and we get:

for my $wortObj (@worte) {
   print "$wortObj->{Index} $wortObj->{Text}\n";
}

For more info on references, start with perlreftut, then maybe read perlref, perldsc, and perlootut.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you. I suspected I was missing something basic. I was even experimenting with using curly brackets - assuming that was enough to tell Perl to use the hash reference instead. Well, again, thank you.
0

Well there are couple of mistakes because of which your code is not working

@worte = {}; 

The above line defines an array wrote and make it first element as an refernce to hash. Which we dont want. We can simply declare an array @wrote

for my $i (0 .. 4){
    my (%wortObj) = (Index => $i, Text => "Text$i"); 
    print "$wortObj{Index} $wortObj{Text}\n"; 
    push @worte, %wortObj; 

The above line tries to store the %wortobj hash in list context which is not possible we need to store it in scalar refernce. We can edit the code as push @worte, \%wortObj;

}

foreach $wortObject (@worte){
    print "$wortObject{Index} $wortObject{Text}\n"; 

The above line tried to print from an hashrefence but the first -> operator is never implied. We can edit it as print "$wortObject->{Index} $wortObject->{Text}\n";

}

5 Comments

oops the same answer :) again
I'd rather have too many than too few answers. Thank you. (I have too few reputation to +1 you, sorry about that)
Cool .. and i would suggest you edit the line @worte = {}; too as it will create an empty hash which may result in error in your foreach loop saying unintialized value
My original code is more complex and uses a different declaration anyway. That's the problem if you try to make a simple example, you sometimes put in additional errors. I have corrected my short example for future reference, though.
cool as long as the code works..!! Never edit a Working code :P

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.