Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > complex data structure

Reply
Thread Tools

complex data structure

 
 
Jeff
Guest
Posts: n/a
 
      06-26-2004
I've created a beast! Here is my data structure:

$VAR1 = 'bunkers';
$VAR2 = {
'items' => [
\[
{
'archie' => 'conservative'
}
],
\[
{
'meathead' => 'liberal'
}
]
]
};
$VAR3 = 'simpsons';
$VAR4 = {
'items' => [
\[
{
'haha' => 'nelson munce'
}
],
\[
{
'whoohoo' => 'homer simpson'
}
]
]
};

How do I access the hash key value pairs? This fails at runtime:
(Not a HASH reference at haha line 22.)

foreach $key (keys %hash){
print "[".$key."]\n";
for $who (@{$hash{$key}{items}}){
foreach $item (keys %{$who}){
print $item . " => " . $who->{$item} . "\n";
}
}
}

TIA,
Jeff
 
Reply With Quote
 
 
 
 
Bob Walton
Guest
Posts: n/a
 
      06-26-2004
Jeff wrote:

> I've created a beast! Here is my data structure:
>
> $VAR1 = 'bunkers';
> $VAR2 = {
> 'items' => [
> \[
> {
> 'archie' => 'conservative'
> }
> ],
> \[
> {
> 'meathead' => 'liberal'
> }
> ]
> ]
> };
> $VAR3 = 'simpsons';
> $VAR4 = {
> 'items' => [
> \[
> {
> 'haha' => 'nelson munce'
> }
> ],
> \[
> {
> 'whoohoo' => 'homer simpson'
> }
> ]
> ]
> };
>
> How do I access the hash key value pairs? This fails at runtime:
> (Not a HASH reference at haha line 22.)
>
> foreach $key (keys %hash){
> print "[".$key."]\n";
> for $who (@{$hash{$key}{items}}){
> foreach $item (keys %{$who}){
> print $item . " => " . $who->{$item} . "\n";
> }
> }
> }

....
> Jeff


That *is* a beast of a structure. I'll take your word for it that that
is really the structure you want (scalar references to array references
included). I also assume that your *original* data structure was a hash
containing $VAR1 through $VAR4 as keys/values, and that you didn't
properly dump a reference to that outside hash, but rather independently
dumped the keys/values to that hash. If so, here you go...

use warnings; #let Perl help you all it can
use strict; #let Perl help you all it can
my $VAR1 = 'bunkers';
my $VAR2 = {
'items' => [
\[
{
'archie' => 'conservative'
}
],
\[
{
'meathead' => 'liberal'
}
]
]
};
my $VAR3 = 'simpsons';
my $VAR4 = {
'items' => [
\[
{
'haha' => 'nelson munce'
}
],
\[
{
'whoohoo' => 'homer simpson'
}
]
]
};
#reconstitute assumed original structure:
my %hash=($VAR1,$VAR2,$VAR3,$VAR4);
=item
How do I access the hash key value pairs? This fails at runtime:
(Not a HASH reference at haha line 22.)
=cut
foreach my $key (keys %hash){
print "[".$key."]\n";
for my $who (@{$hash{$key}->{items}}){
foreach my $item (keys %{${$$who}[0]}){
print $item . " => " . $$who->[0]->{$item} . "\n";
}
}
}

HTH. You didn't show enough of your intended data structure for me to
know if you actually intend to have one-element arrays where I show them
in the code -- if they will actually have more than one element, you
will need to introduce another foreach loop to iterate over them. My
guess this isn't the data structure you really want.

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

 
Reply With Quote
 
 
 
 
Jeff
Guest
Posts: n/a
 
      06-26-2004
Bob Walton wrote:
> Jeff wrote:
>
>> I've created a beast! Here is my data structure:
>>
>> $VAR1 = 'bunkers';
>> $VAR2 = {
>> 'items' => [
>> \[
>> {
>> 'archie' => 'conservative'
>> }
>> ],
>> \[
>> {
>> 'meathead' => 'liberal'
>> }
>> ]
>> ]
>> };
>> $VAR3 = 'simpsons';
>> $VAR4 = {
>> 'items' => [
>> \[
>> {
>> 'haha' => 'nelson munce'
>> }
>> ],
>> \[
>> {
>> 'whoohoo' => 'homer simpson'
>> }
>> ]
>> ]
>> };
>>
>> How do I access the hash key value pairs? This fails at runtime:
>> (Not a HASH reference at haha line 22.)
>>
>> foreach $key (keys %hash){
>> print "[".$key."]\n";
>> for $who (@{$hash{$key}{items}}){
>> foreach $item (keys %{$who}){
>> print $item . " => " . $who->{$item} . "\n";
>> }
>> }
>> }

>
> ...
>
>> Jeff

>
>
> That *is* a beast of a structure. I'll take your word for it that that
> is really the structure you want (scalar references to array references
> included). I also assume that your *original* data structure was a hash
> containing $VAR1 through $VAR4 as keys/values, and that you didn't
> properly dump a reference to that outside hash, but rather independently
> dumped the keys/values to that hash. If so, here you go...
>
> use warnings; #let Perl help you all it can
> use strict; #let Perl help you all it can
> my $VAR1 = 'bunkers';
> my $VAR2 = {
> 'items' => [
> \[
> {
> 'archie' => 'conservative'
> }
> ],
> \[
> {
> 'meathead' => 'liberal'
> }
> ]
> ]
> };
> my $VAR3 = 'simpsons';
> my $VAR4 = {
> 'items' => [
> \[
> {
> 'haha' => 'nelson munce'
> }
> ],
> \[
> {
> 'whoohoo' => 'homer simpson'
> }
> ]
> ]
> };
> #reconstitute assumed original structure:
> my %hash=($VAR1,$VAR2,$VAR3,$VAR4);
> =item
> How do I access the hash key value pairs? This fails at runtime:
> (Not a HASH reference at haha line 22.)
> =cut
> foreach my $key (keys %hash){
> print "[".$key."]\n";
> for my $who (@{$hash{$key}->{items}}){
> foreach my $item (keys %{${$$who}[0]}){
> print $item . " => " . $$who->[0]->{$item} . "\n";
> }
> }
> }
>
> HTH. You didn't show enough of your intended data structure for me to
> know if you actually intend to have one-element arrays where I show them
> in the code -- if they will actually have more than one element, you
> will need to introduce another foreach loop to iterate over them. My
> guess this isn't the data structure you really want.
>


I'm certainly open to suggestions. Here is the method that creates the
hash:

sub getHashes()
{
my $this = shift;
my ($sep,$bad_programmer) = @_;
my (%hash, $hash);
my $lines = "";
my (@list, @cols);
my ($left,$right);
my ($prefix, $items);

if(open(FILE, "<" . $this->{"file"})){
flock(FILE, $LOCK_EX);
while(<FILE>){
next if /^$/;
next if /^\s*#/;
$lines .= $_;
}
flock(FILE, $LOCK_UN);
close(FILE);
}

$prefix = 'default';
$items = 'items';
foreach my $thing ( split( /\n/, $lines ) ){
if($thing =~ m/^\[([^\]]+)\]$/){
$prefix = $1;
print "PREFIX: $prefix\n";
next;
}
($left,$right) = split( /$sep/, $thing );
# Trim begnining and trailing whitespace
$left=~s/^\s+//;
$right=~s/^\s+//;
$left=~s/\s+$//;
$right=~s/\s+$//;
#$hash{$prefix}{$items} = [{ $left => $right, }];
push(@{$hash{$prefix}{$items}}, \[{ $left => $right, }]);
}
return %hash;
}

I had really wanted to push arrays (not refs) on $hash{$prefix}{$items}

Jeff

 
Reply With Quote
 
Sherm Pendley
Guest
Posts: n/a
 
      06-26-2004
> foreach $item (keys %{$who}){

The major problem in the above is that $who is neither a Simpsons reference
nor a Bunkers reference, it's a Dr. Seuss reference.

Okay, seriously... Like the error says, $who is not a hash ref, it's an
array ref, so the above should be:

foreach $item (@{$who}) {

Also, the array referred to by $who contains two items - each is a reference
to a reference (not a typo - note the backslash in the Data:umper output)
to an array. The inner array contains a single item, which is a reference
to a hash containing a single item.

To work with the code as given, your data structure would need to look in
part like this:

$VAR4 = {
'items' => {
'haha' => 'nelson munce',
'whoohoo' => 'homer simpson'
}
};

If the data is correct as given, then the code will need to be restructured
to correctly deal with the additional layers of array references.

To help deal with these issues, I suggest reading 'perldoc
perlreftut' (References Tutorial), 'perldoc perldsc' (Data Structures
Cookbook), and 'perldoc perllol' (Lists of Lists), in that order.

sherm--

--
Cocoa programming in Perl: http://camelbones.sourceforge.net
Hire me! My resume: http://www.dot-app.org
 
Reply With Quote
 
Bob Walton
Guest
Posts: n/a
 
      06-26-2004
Jeff wrote:

> Bob Walton wrote:
>
>> Jeff wrote:

....
> I'm certainly open to suggestions. Here is the method that creates the
> hash:
>
> sub getHashes()
> {
> my $this = shift;
> my ($sep,$bad_programmer) = @_;
> my (%hash, $hash);
> my $lines = "";
> my (@list, @cols);
> my ($left,$right);
> my ($prefix, $items);
>
> if(open(FILE, "<" . $this->{"file"})){
> flock(FILE, $LOCK_EX);
> while(<FILE>){
> next if /^$/;
> next if /^\s*#/;
> $lines .= $_;
> }
> flock(FILE, $LOCK_UN);
> close(FILE);
> }



else { #you don't really want to continue if the open failed
die "file open failed for $this->{file}"
}


>
> $prefix = 'default';
> $items = 'items';
> foreach my $thing ( split( /\n/, $lines ) ){
> if($thing =~ m/^\[([^\]]+)\]$/){
> $prefix = $1;
> print "PREFIX: $prefix\n";
> next;
> }
> ($left,$right) = split( /$sep/, $thing );
> # Trim begnining and trailing whitespace
> $left=~s/^\s+//;
> $right=~s/^\s+//;
> $left=~s/\s+$//;
> $right=~s/\s+$//;
> #$hash{$prefix}{$items} = [{ $left => $right, }];



In the above (if it weren't commented out), you would be storing a
reference to a one element anonymous array, the contents of which are a
reference to an anonymous one-key hash. If you just have two things to
store, just put them in the array: = [$left,$right]; It just garbages
things up to have one-element arrays and one-key hashes.


> push(@{$hash{$prefix}{$items}}, \[{ $left => $right, }]);



Here, you are pushing a reference to a reference to a one-element
anonymous array, the element of which is a reference to a one-key
anonymous hash. That's *way* out of control: [untested]

push(@{$hash{$prefix}{%items}},[$left,$right];

should accomplish the same data storage task, but in a much cleaner fashion.

Note that

$q=[1,2,3,4];

stores a reference to an anonymous 4-element array into scalar variable
$q. It is not necessary or desirable to do:

$q=\[1,2,3,4];

which stores a reference to a reference to an anonymous 4-element array
in $q.


> }
> return %hash;
> }
>
> I had really wanted to push arrays (not refs) on $hash{$prefix}{$items}



I'm not sure what your are trying to say in that statement. A hash
element (or an array element for that matter) can only hold one sort of
thing: a scalar. Therefore, you can't "push arrays on $hash{...}" --
but you *can* place a *reference* to an array in a hash as a hash
element value.

Check out:

perldoc perldsc
perldoc perllol
perldoc perlref

etc.


> Jeff


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

 
Reply With Quote
 
Jeff
Guest
Posts: n/a
 
      06-26-2004
Bob Walton wrote:
> Jeff wrote:
>
>> Bob Walton wrote:
>>
>>> Jeff wrote:

>
> ...
>
>> I'm certainly open to suggestions. Here is the method that creates the
>> hash:
>>
>> sub getHashes()
>> {
>> my $this = shift;
>> my ($sep,$bad_programmer) = @_;
>> my (%hash, $hash);
>> my $lines = "";
>> my (@list, @cols);
>> my ($left,$right);
>> my ($prefix, $items);
>>
>> if(open(FILE, "<" . $this->{"file"})){
>> flock(FILE, $LOCK_EX);
>> while(<FILE>){
>> next if /^$/;
>> next if /^\s*#/;
>> $lines .= $_;
>> }
>> flock(FILE, $LOCK_UN);
>> close(FILE);
>> }

>
>
>
> else { #you don't really want to continue if the open failed
> die "file open failed for $this->{file}"
> }
>
>
>>
>> $prefix = 'default';
>> $items = 'items';
>> foreach my $thing ( split( /\n/, $lines ) ){
>> if($thing =~ m/^\[([^\]]+)\]$/){
>> $prefix = $1;
>> print "PREFIX: $prefix\n";
>> next;
>> }
>> ($left,$right) = split( /$sep/, $thing );
>> # Trim begnining and trailing whitespace
>> $left=~s/^\s+//;
>> $right=~s/^\s+//;
>> $left=~s/\s+$//;
>> $right=~s/\s+$//;
>> #$hash{$prefix}{$items} = [{ $left => $right, }];

>
>
>
> In the above (if it weren't commented out), you would be storing a
> reference to a one element anonymous array, the contents of which are a
> reference to an anonymous one-key hash. If you just have two things to
> store, just put them in the array: = [$left,$right]; It just garbages
> things up to have one-element arrays and one-key hashes.
>
>
>> push(@{$hash{$prefix}{$items}}, \[{ $left => $right, }]);

>
>
>
> Here, you are pushing a reference to a reference to a one-element
> anonymous array, the element of which is a reference to a one-key
> anonymous hash. That's *way* out of control: [untested]
>
> push(@{$hash{$prefix}{%items}},[$left,$right];
>
> should accomplish the same data storage task, but in a much cleaner
> fashion.
>
> Note that
>
> $q=[1,2,3,4];
>
> stores a reference to an anonymous 4-element array into scalar variable
> $q. It is not necessary or desirable to do:
>
> $q=\[1,2,3,4];
>
> which stores a reference to a reference to an anonymous 4-element array
> in $q.
>
>
>> }
>> return %hash;
>> }
>>
>> I had really wanted to push arrays (not refs) on $hash{$prefix}{$items}

>
>
>
> I'm not sure what your are trying to say in that statement. A hash
> element (or an array element for that matter) can only hold one sort of
> thing: a scalar. Therefore, you can't "push arrays on $hash{...}" --
> but you *can* place a *reference* to an array in a hash as a hash
> element value.
>
> Check out:
>
> perldoc perldsc
> perldoc perllol
> perldoc perlref
>
> etc.
>
>


Thanks. That helped considerably. This is closer to what I wanted:

sub getHashes()
{
my $this = shift;
my ($sep,$bad_programmer) = @_;
my (%hash, $rec);
my $lines = "";
my ($prefix);

if(open(FILE, "<" . $this->{"file"})){
flock(FILE, $LOCK_EX);
while(<FILE>){
next if /^$/;
next if /^\s*#/;
$lines .= $_;
}
flock(FILE, $LOCK_UN);
close(FILE);
}

$prefix = 'default';
$rec = {};
$hash{$prefix} = $rec;
foreach my $thing (split(/\n/, $lines)){
$thing=~s/^\s+//; # trim leading white space
$thing=~s/\s+$//; # trim trailing white space
if($thing =~ m/^\[([^\]]+)\]$/){
$prefix = $1;
$rec = {};
$hash{$prefix} = $rec;
next;
} else {
my($key, $value) = split /$sep/, $thing;
$key=~s/^\s+//;
$value=~s/^\s+//;
$key=~s/\s+$//;
$value=~s/\s+$//;
$rec->{$key} = $value;
}
}
return %hash;
}



 
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
Accessing complex data from a linked list based data structure.. Ram C Programming 3 03-24-2009 02:15 AM
Memory leak issue with complex data structure Alan Franzoni Python 2 07-05-2007 07:50 AM
Need advice to choise complex data structure (STL) Sigmathaar C++ 3 12-06-2005 03:56 PM
complex data structure - insert value spar Python 4 10-11-2004 07:24 AM
complex data structure in httpcookie Waqqas Farooq ASP .Net 1 06-30-2004 12:51 PM



Advertisments