Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > array of hashrefs (nested)

Reply
Thread Tools

array of hashrefs (nested)

 
 
monkeys paw
Guest
Posts: n/a
 
      10-27-2003
I have the following code that is behaving stragely:

use Data:umper;

%pair = (
'Subject' => 'Vapor,Bob-war,new-tag',
'Analyst' => 'simi'
);

for my $heading (sort keys %pair) {
@tags = ();
for my $tag (split /,/, $pair{$heading}) {
push @tags, {tag_key => $tag, tag_name => $tag};
}
push @headings, {
heading_name => $heading,
tags => \@tags,
};
}
print Dumper(\@headings) ;

The output is:

HAT2: $VAR1 = [
{
'tags' => [
{
'tag_key' => 'Vapor',
'tag_name' => 'Vapor'
},
{
'tag_key' => 'Bob-war',
'tag_name' => 'Bob-war'
},
{
'tag_key' => 'new-tag',
'tag_name' => 'new-tag'
}
],
'heading_name' => 'Analyst'
},
{
'tags' => $VAR1->[0]{'tags'},
'heading_name' => 'Subject'
}
];

What is causing the 'tags' => $VAR1->[0]{'tags'}, line to
show up?? I would expect it to be

'tags' => {
'tag_key' => 'new-tag',
'tag_name' => 'new-tag'
}



 
Reply With Quote
 
 
 
 
Glenn Jackman
Guest
Posts: n/a
 
      10-27-2003
monkeys paw <(E-Mail Removed)> wrote:
[...]
> for my $heading (sort keys %pair) {
> @tags = ();


You want: my @tags = ();

[...]
> What is causing the 'tags' => $VAR1->[0]{'tags'}, line to
> show up?? I would expect it to be


--
Glenn Jackman
NCF Sysadmin
http://www.velocityreviews.com/forums/(E-Mail Removed)
 
Reply With Quote
 
 
 
 
monkeys paw
Guest
Posts: n/a
 
      10-27-2003
Glenn Jackman wrote:

> monkeys paw <(E-Mail Removed)> wrote:
> [...]
>> for my $heading (sort keys %pair) {
>> @tags = ();

>
> You want: my @tags = ();
>
> [...]
>> What is causing the 'tags' => $VAR1->[0]{'tags'}, line to
>> show up?? I would expect it to be

>

Thanks Glenn, that does work. Not sure why tho??
 
Reply With Quote
 
Roy Johnson
Guest
Posts: n/a
 
      10-27-2003
You are using a reference to a global variable, @tags, which you are
overwriting each pass through the loop.
use strict;
would have helped. Then you would have known to declare it as "my" and
it probably would have given you the results you were expecting.

VAR1 is Dumper's name for the reference to @tags.
 
Reply With Quote
 
James E Keenan
Guest
Posts: n/a
 
      10-27-2003
monkeys paw <(E-Mail Removed)> wrote in message news:<xbbnb.40819$Fm2.16610@attbi_s04>...
> I have the following code that is behaving stragely:
>
> use Data:umper;
>
> %pair = (
> 'Subject' => 'Vapor,Bob-war,new-tag',
> 'Analyst' => 'simi'
> );
>
> for my $heading (sort keys %pair) {
> @tags = ();
> for my $tag (split /,/, $pair{$heading}) {
> push @tags, {tag_key => $tag, tag_name => $tag};
> }
> push @headings, {


You obviously were not running with 'use strict;' called. Otherwise
you would have gotten a compilation error right here.

> heading_name => $heading,
> tags => \@tags,
> };
> }
> print Dumper(\@headings) ;
>
> The output is:
>
> HAT2: $VAR1 = [
> {
> 'tags' => [
> {
> 'tag_key' => 'Vapor',
> 'tag_name' => 'Vapor'
> },
> {
> 'tag_key' => 'Bob-war',
> 'tag_name' => 'Bob-war'
> },
> {
> 'tag_key' => 'new-tag',
> 'tag_name' => 'new-tag'
> }
> ],
> 'heading_name' => 'Analyst'
> },
> {
> 'tags' => $VAR1->[0]{'tags'},
> 'heading_name' => 'Subject'
> }
> ];
>
> What is causing the 'tags' => $VAR1->[0]{'tags'}, line to
> show up?? I would expect it to be
>
> 'tags' => {
> 'tag_key' => 'new-tag',
> 'tag_name' => 'new-tag'
> }


Once I properly scoped all variables with 'my' and used strict, I got
these results:

$VAR1 = [
{
'heading_name' => 'Analyst',
'tags' => [
{
'tag_name' => 'simi',
'tag_key' => 'simi'
}
]
},
{
'heading_name' => 'Subject',
'tags' => [
{
'tag_name' => 'Vapor',
'tag_key' => 'Vapor'
},
{
'tag_name' => 'Bob-war',
'tag_key' => 'Bob-war'
},
{
'tag_name' => 'new-tag',
'tag_key' => 'new-tag'
}
]
}
];

jimk
 
Reply With Quote
 
Tad McClellan
Guest
Posts: n/a
 
      10-27-2003
monkeys paw <(E-Mail Removed)> wrote:

> I have the following code that is behaving stragely:



If you drive without your seatbelt fastened, then you should
be prepared for a trip through the windshield.

use strict;

would have saved you from this problem...


> for my $heading (sort keys %pair) {
> @tags = ();
> for my $tag (split /,/, $pair{$heading}) {
> push @tags, {tag_key => $tag, tag_name => $tag};
> }
> push @headings, {
> heading_name => $heading,
> tags => \@tags,
> };
> }



--
Tad McClellan SGML consulting
(E-Mail Removed) Perl programming
Fort Worth, Texas
 
Reply With Quote
 
monkeys paw
Guest
Posts: n/a
 
      10-27-2003

> monkeys paw <(E-Mail Removed)> wrote:
>
>> I have the following code that is behaving stragely:

>
>
> If you drive without your seatbelt fastened, then you should
> be prepared for a trip through the windshield.
>
> use strict;
>
> would have saved you from this problem...
>


Thanks all for the advice. Upon closer inspection i understand
how localizing the @tags array would save me this problem. However,
just as a side note, "use strict" would not detect this error that
i see. I was overwriting a global, which is perfectly legal.

Anyway, just wanted to make sure i wasn't missing something on
this corrolary...thanks again for the help.

>
>> for my $heading (sort keys %pair) {
>> @tags = ();
>> for my $tag (split /,/, $pair{$heading}) {
>> push @tags, {tag_key => $tag, tag_name => $tag};
>> }
>> push @headings, {
>> heading_name => $heading,
>> tags => \@tags,
>> };
>> }

>
>


 
Reply With Quote
 
Ben Morrow
Guest
Posts: n/a
 
      10-28-2003

(E-Mail Removed) wrote:
> Thanks all for the advice. Upon closer inspection i understand
> how localizing the @tags array would save me this problem. However,
> just as a side note, "use strict" would not detect this error that
> i see. I was overwriting a global, which is perfectly legal.


....except under strictures . That is of course not strictly (sic)
true: it is perfectly possible to use package globals under 'strict',
bit you must make it clear that you meant to and haven't simply made a
mistake by either declaring them with 'our' or fully qualifying the
name.

Ben

--
For the last month, a large number of PSNs in the Arpa[Inter-]net have been
reporting symptoms of congestion ... These reports have been accompanied by an
increasing number of user complaints ... As of June,... the Arpanet contained
47 nodes and 63 links. [ftp://rtfm.mit.edu/pub/arpaprob.txt] * (E-Mail Removed)
 
Reply With Quote
 
Chris Mattern
Guest
Posts: n/a
 
      10-28-2003
monkeys paw wrote:
>>monkeys paw <(E-Mail Removed)> wrote:
>>
>>
>>>I have the following code that is behaving stragely:

>>
>>
>>If you drive without your seatbelt fastened, then you should
>>be prepared for a trip through the windshield.
>>
>> use strict;
>>
>>would have saved you from this problem...
>>

>
>
> Thanks all for the advice. Upon closer inspection i understand
> how localizing the @tags array would save me this problem. However,
> just as a side note, "use strict" would not detect this error that
> i see. I was overwriting a global, which is perfectly legal.


Except that when you do "use strict;", Perl doesn't merrily assume
that all your undeclared variables are globals. You have to declare
them as either local (my) or global (global) or whatever. Strict
will kill the compilation if you attempt to use a variable you haven't
declared. "use strict" doesn't stop you from hanging yourself, but it
does at least make you write a requisition order for the rope.

Chris Mattern

>
> Anyway, just wanted to make sure i wasn't missing something on
> this corrolary...thanks again for the help.
>
>
>>> for my $heading (sort keys %pair) {
>>> @tags = ();
>>> for my $tag (split /,/, $pair{$heading}) {
>>> push @tags, {tag_key => $tag, tag_name => $tag};
>>> }
>>> push @headings, {
>>> heading_name => $heading,
>>> tags => \@tags,
>>> };
>>> }

>>
>>

>



 
Reply With Quote
 
Bob Walton
Guest
Posts: n/a
 
      10-28-2003
monkeys paw wrote:

>>monkeys paw <(E-Mail Removed)> wrote:

....


>> use strict;
>>
>>would have saved you from this problem...
>>
>>

>
> Thanks all for the advice. Upon closer inspection i understand
> how localizing the @tags array would save me this problem. However,
> just as a side note, "use strict" would not detect this error that
> i see. I was overwriting a global, which is perfectly legal.
>
> Anyway, just wanted to make sure i wasn't missing something on
> this corrolary...thanks again for the help.
>
>
>>> for my $heading (sort keys %pair) {
>>> @tags = ();
>>> for my $tag (split /,/, $pair{$heading}) {
>>> push @tags, {tag_key => $tag, tag_name => $tag};
>>> }
>>> push @headings, {
>>> heading_name => $heading,
>>> tags => \@tags,
>>> };
>>> }

....


I think perhaps you still don't understand. Here is a short program and
its output that illustrates the essence of the problem:

@array=(1,2,3);
$array_ref1=\@array;
@array=(4,5,6);
$array_ref2=\@array;
print @$array_ref1,"\n";
print @$array_ref2,"\n";

D:\junk>perl junk401.pl
456
456

D:\junk>

The problem (if you wish to call it a problem -- it is expected and
documented behavior) is that $array_ref1 and $array_ref2 are references
to the *exact same array*, the one called @array. The fact that the
*contents* of this array changed do not make the references change what
array they are pointing to. There *is only one* array, with two
references pointing to it. Hence when you're all done, both references
point to the same set of values. If you had 100 references, they would
all point to the same array.

Now, use strict; will in and of itself not fix this:

use warnings;
use strict;
my @array;
@array=(1,2,3);
my $array_ref1=\@array;
@array=(4,5,6);
my $array_ref2=\@array;
print @$array_ref1,"\n";
print @$array_ref2,"\n";

gives:

D:\junk>perl junk401a.pl
456
456

D:\junk>

And for the very same reasons. One can add a "my" to each array
definition and solve the problem:

use warnings;
use strict;
my @array=(1,2,3);
my $array_ref1=\@array;
my @array=(4,5,6);
my $array_ref2=\@array;
print @$array_ref1,"\n";
print @$array_ref2,"\n";

which gives:

D:\junk>perl junk401b.pl
"my" variable @array masks earlier declaration in same scope at
junk401.pl line 5.
123
456

D:\junk>

but at the expense of a warning. So how should this be handled? One
good approach is to do what you meant to do: make a reference to an
anonymous copy of the array each time, like:

use warnings;
use strict;
my @array;
@array=(1,2,3);
my $array_ref1=[@array];
@array=(4,5,6);
my $array_ref2=[@array];
print @$array_ref1,"\n";
print @$array_ref2,"\n";

which gives the desired:

D:\junk>perl junk401c.pl
123
456

D:\junk>

Previous posters have mentioned that use strict; would point out the
problem. Not really, in this case, although, since @tags was defined in
a loop, saying my @tags; would have solved the immediate problem -- but
not if there had been a reference taken to the array, a modification to
the array, and then another reference during the execution of the loop.
But use strict; is hugely beneficial for many many problems, and
should *always* be used, along with use warnings; , in all development code.

HTH.
--
Bob Walton
Email: http://bwalton.com/cgi-bin/emailbob.pl

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
const and array of array (of array ...) Mara Guida C Programming 3 09-03-2009 07:54 AM
sorting an array of hashrefs John W. Krahn Perl Misc 1 08-29-2006 08:29 PM
iterating over a hashref of hashrefs Sam Perl Misc 6 06-15-2005 10:44 AM
Length of Array of Array of Array Tom Perl Misc 3 12-20-2004 05:23 PM
grouping hashrefs to trees Matija Papec Perl Misc 1 11-16-2003 04:38 PM



Advertisments