Icarus
Icarus

Reputation: 5

Access values from Hash inside Array

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?

Upvotes: 0

Views: 375

Answers (2)

Gaurav
Gaurav

Reputation: 114

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";

}

Upvotes: 0

amon
amon

Reputation: 57600

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.

Upvotes: 1

Related Questions