Parse data structure

D

Davidcollins001

I am looking to parse data into a complex structure of hashes and
arrays. I have been reading the data structures cookbook on the CPAN
website
(http://search.cpan.org/~nwclark/perl-5.8.7/pod/perldsc.pod#MORE_ELABORATE_RECORDS).
At the bottom they say that it is sometimes easier to have the file as
the data structure that would be used to create the structure in perl.

I was wondering how to do this? I have been playing around trying to
learn how to use complex structures, but I can't figure out how to get
perl to parse code into a hash? I did initially think of placing the
data structure in a file and setting the hash equal to it, but that
doesn't work. am I thinking too simplistic?

This is my data structure that I am playing around with in a separate
file:

may => [
[2,'train',20.00, 'expensive'],
[6,'train',15],
[19,'car',18,'best way']
],
june => [
[5,'car',2.00],
[9,'train',1],
[19,'cat',18,'best way']
],
july => [
[14,'plane',100],
[23,'boat',20]
],


And this is the code I have to read and print it out:


## read above from file into hash
open(DATA, "<$file");
my %HoLoL=<DATA>;
close(DATA);


## print each element separately
foreach my $date ( keys %HoLoL )
{
print "$date";
for(my $i=0; $i<($#{@{$HoLoL{$date}}}+1); $i++)
{
for(my $j=0; $j<($#{ $HoLoL{$date} [$i] }+1); $j++)
{
print "\t ${ $HoLoL{$date} [$i]}[$j] ";
}
print "\n";
}
}
print "\n";


(I know I can print it out easier and probably quicker with one less
loop at least, I just wanted to know how to get to each element.)

Thanks in advance
 
B

Bob Walton

I am looking to parse data into a complex structure of hashes and
arrays. I have been reading the data structures cookbook on the CPAN
website
(http://search.cpan.org/~nwclark/perl-5.8.7/pod/perldsc.pod#MORE_ELABORATE_RECORDS).
At the bottom they say that it is sometimes easier to have the file as
the data structure that would be used to create the structure in perl.

I was wondering how to do this? I have been playing around trying to
learn how to use complex structures, but I can't figure out how to get
perl to parse code into a hash? I did initially think of placing the
data structure in a file and setting the hash equal to it, but that
doesn't work. am I thinking too simplistic?

This is my data structure that I am playing around with in a separate
file:

may => [
[2,'train',20.00, 'expensive'],
[6,'train',15],
[19,'car',18,'best way']
],
june => [
[5,'car',2.00],
[9,'train',1],
[19,'cat',18,'best way']
],
july => [
[14,'plane',100],
[23,'boat',20]
],


And this is the code I have to read and print it out:


## read above from file into hash
open(DATA, "<$file");
my %HoLoL=<DATA>;
close(DATA);


## print each element separately
foreach my $date ( keys %HoLoL )
{
print "$date";
for(my $i=0; $i<($#{@{$HoLoL{$date}}}+1); $i++)
{
for(my $j=0; $j<($#{ $HoLoL{$date} [$i] }+1); $j++)
{
print "\t ${ $HoLoL{$date} [$i]}[$j] ";
}
print "\n";
}
}
print "\n";


(I know I can print it out easier and probably quicker with one less
loop at least, I just wanted to know how to get to each element.)

Thanks in advance

Well, if you want to make your data files be Perl code, make it
valid Perl, something like:

$HoLoL={
may => [
[2,'train',20.00, 'expensive'],
[6,'train',15],
[19,'car',18,'best way']
],
june => [
[5,'car',2.00],
[9,'train',1],
[19,'cat',18,'best way']
],
july => [
[14,'plane',100],
[23,'boat',20]
],
};

Then you can write a Perl program to execute this data file as
follows, taking advantage of an already-written module to print
the data structure (which module, incidentally, generates valid
Perl code):

use strict;
use warnings;
our $HoLoL;
do 'junk566.txt';
use Data::Dumper;
print Dumper($HoLoL);

When run, this generates:

D:\junk>perl junk566.pl
$VAR1 = {
'june' => [
[
5,
'car',
'2'
],
[
9,
'train',
1
],
[
19,
'cat',
18,
'best way'
]
],
'may' => [
[
2,
'train',
'20',
'expensive'
],
[
6,
'train',
15
],
[
19,
'car',
18,
'best way'
]
],
'july' => [
[
14,
'plane',
100
],
[
23,
'boat',
20
]
]
};

D:\junk>

HTH.
 
B

Ben Morrow

Quoth Bob Walton said:
This is my data structure that I am playing around with in a separate
file:

may => [
[2,'train',20.00, 'expensive'],
[6,'train',15],
[19,'car',18,'best way']
],
june => [
[5,'car',2.00],
[9,'train',1],
[19,'cat',18,'best way']
],
july => [
[14,'plane',100],
[23,'boat',20]
],

Well, if you want to make your data files be Perl code, make it
valid Perl, something like:

$HoLoL={
may => [
[2,'train',20.00, 'expensive'],
[6,'train',15],
[19,'car',18,'best way']
],
june => [
[5,'car',2.00],
[9,'train',1],
[19,'cat',18,'best way']
],
july => [
[14,'plane',100],
[23,'boat',20]
],
};

Then you can write a Perl program to execute this data file as
follows, taking advantage of an already-written module to print
the data structure (which module, incidentally, generates valid
Perl code):

use strict;
use warnings;
our $HoLoL;
do 'junk566.txt';
use Data::Dumper;
print Dumper($HoLoL);

You can also avoid having to have the name of the variable in the file
(generally a good idea: firstly data files shouldn't need to know what
variables in the program they will be read into; secondly it means you
don't need to use a global, which is always a good thing):

#!/usr/bin/perl -l

use strict;
use warnings;
use Data::Dump qw/dump/; # I prefer this to Data::Dumper

my $HoLoL = { do "junk566.txt" };
print dump $HoLoL;

__END__

Note that this technique, while powerful, is not terribly safe. It's
basically equivalent to string eval, so all the caveats of that apply.
You don't get very clear error messages if the file contains syntax
errors, and dealing with this is somewhat tricky. More importantly, it
is possible to muck up anything in the program with an incorrect or
malicious data file, which leads to difficult-to-find bugs and security
holes (where that is important).

For an alternative way of creating data files which mimic the Perl
structures they read into, try YAML. For example:

travel.yml:
july:
-
- 14
- plane
- 100
-
- 23
- boat
- 20
june:
-
- 5
- car
- 2
-
- 9
- train
- 1
-
- 19
- cat
- 18
- best way
may:
-
- 2
- train
- 20
- expensive
-
- 6
- train
- 15
-
- 19
- car
- 18
- best way

Then write something like:

#!/usr/bin/perl -l

use strict;
use warnings;
use YAML;
use Data::Dump qw/dump/;

my $h = YAML::LoadFile 'travel.yml';
print dump $h;

__END__

It is possible to write YAML in a more Perlish style, like

{
may: [
[2, train, expensive],
[6, train, 15]
]
}

but YAML.pm currently doesn't seem to load these. YAML::Syck (which is
based on libsyck, written in C) does, but I can't seem to make it emit
them, if that's a concern for you. See
http://yaml4r.sourceforge.net/cookbook/ for an intro: don't worry that
it's for Ruby, most of the syntax is the same as Perl.

Ben
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top