Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Keyed list in perl

by mc_pandey (Initiate)
on Mar 13, 2007 at 10:34 UTC ( [id://604499]=perlquestion: print w/replies, xml ) Need Help??

mc_pandey has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

I am new to perl ..can someone please help me in handling keyed list in perl?

I have a keyed list in a file f1.chart as-

{chart {{1 {{title title_1} {xlable X-lab} {ylable Y-lab} {description + desc1} {type line} {series {{1 {{x_data {1 2 3 4 5}} {y_data {20 90 +60 50 30}}}}}}}}}}

Now i want to get the value of x_data (1 2 3 4 5) and y_data (20 90 60 50 30) in a perl script.

How do i get that?

20070313 Janitored by Corion: Added formatting, code tags, as per Writeup Formatting Tips

Replies are listed 'Best First'.
Re: Keyed list in perl
by lima1 (Curate) on Mar 13, 2007 at 11:02 UTC
    Do you want to parse the complete file into a nested data structure? There are plenty of modules on CPAN. Not sure which one is the best here (Parse::RecDescent is nice) Or is it just a pattern matching problem:
    my $filecontent = "{type line} {series {{1 {{x_data {1 2 3 4 5}} {y"; my ( $xdata ) = $filecontent =~ / x_data .*? ({.*?})/xms; my @x; while ($xdata =~ /(\d+)/g) { push @x, $1; }
    ?
Re: Keyed list in perl
by ferreira (Chaplain) on Mar 13, 2007 at 14:25 UTC

    Your syntax and data structure looks very much like an s-expression (or Lisp list) with some minor differences: like braces instead of parentheses.

    The following is a partial solution to your question after massaging the input a little bit. First, braces are replaced by parentheses. Then, all underscores have been replaced by hyphens (this is due to a current limitation of the module used below). And the input file looks like this:

    (chart ((1 ((title title-1) (xlable X-lab) (ylable Y-lab) (description + desc1) (type line) (series ((1 ((x-data (1 2 3 4 5)) (y-data (20 90 +60 50 30))))))))))

    There is in CPAN a quite recent module named Data::SExpression (and there is some problem with the current version 0.33 and so I recommend installing the former — for example, say install NELHAGE/Data-SExpression-0.32.tar.gz in the CPAN shell instead of just install Data::SExpression). This module is able to parse the input above.

    But that does not mean it would turn into a handy data structure. Instead it is all composed of array refs that made things quite difficult to access.

    [ "chart", [ [ 1, [ ["title", "title-1"], ["xlable", "X-lab"], ["ylable", "Y-lab"], ["description", "desc1"], ["type", "line"], [ "series", [ [ 1, [["x-data", [1, 2, 3, 4, 5]], ["y-data", [20, 90, 60, 50 +, 30]]], ], ], ], ], ], ], ]

    Making some assumptions on your data, I wrote some code to turn that into a nice hash of hashes. Like this:

    { chart => { description => "desc1", series => { "x-data" => [1, 2, 3, 4, 5], "y-data" => [20, 90, 60, 50, 30] }, title => "title-1", type => "line", xlable => "X-lab", ylable => "Y-lab", }, }
    and then your request
    Now i want to get the value of x_data (1 2 3 4 5) and y_data (20 90 60 50 30)
    turned into a trivial thing:
    use Data::Dump qw(dump); print "x_data: ", dump($keyed_list->{chart}->{series}->{"x-data"}), "\ +n"; print "y_data: ", dump($keyed_list->{chart}->{series}->{"y-data"}), "\ +n"; # which outputs #x_data: [1, 2, 3, 4, 5] #y_data: [20, 90, 60, 50, 30]
    The entire code which I experimented against your data is:
Re: Keyed list in perl
by siva kumar (Pilgrim) on Mar 13, 2007 at 11:01 UTC
    If you want to do this with regex, you can use the following code.
    $line = "{chart {{1 {{title title_1} {xlable X-lab} {ylable Y-lab} {de +scription desc1} {type line} {series {{1 {{x_data {1 2 3 4 5}} {y_dat +a {20 90 60 50 30}}}}}}}}}}"; $line =~ /x_data\s+\{(.*?)\}/; print "X DATA : $1 \n"; $line =~ /y_data\s+\{(.*?)\}/; print "Y DATA : $1 \n";
    UPDATE: Enclose the matching expression within if block.
    if ($line =~ /x_data\s+\{(.*?)\}/) { print "X DATA : $1 \n"; } if ($line =~ /y_data\s+\{(.*?)\}/) { print "Y DATA : $1 \n"; }
Re: Keyed list in perl
by whereiskurt (Friar) on Mar 13, 2007 at 13:19 UTC
    The 'series { 1 {{...}}' implies that there might be multiple groups of xy_data. If that's the case you're going to need some looping or an actual parse tree. If not, I think the REGEXP posted is the simplest solution. KPH
Re: Keyed list in perl
by ww (Archbishop) on Mar 13, 2007 at 14:53 UTC
Re: Keyed list in perl
by pKai (Priest) on Mar 13, 2007 at 23:30 UTC

    Just because it's possible, here a self-contained parser to convert the string into an AoA in the sense of ferreira above

    use strict; use warnings; use Data::Dumper; # read text from DATA my $text = do { local $/; <DATA> }; # parse text and convert to AoA my @stack; while ($text =~ m/\G([\w-]+|.)/sg) { my $tok = $1; if ($tok eq '{' or $tok =~ /^\w/) { push @stack, $tok; } elsif ($tok eq '}') { # stack: ... '{' key val(s) my $arr = []; while ($stack[-1] ne '{') { unshift @$arr, pop @stack; } pop @stack; # '{' push @stack, $arr; } } print Dumper(\@stack); __DATA__ {chart { {1 { {title title_1} {xlable X-lab} {ylable Y-lab} {description desc1} {type line} {series { {1 { {x_data {1 2 3 4 5} } {y_data {20 90 60 50 30}} } } } } } } } }

    Of course, well-formedness is not tested but just assumed. So no reasonable behaviour, when the input does not conform to the formatting assumptions.

    Trying to build the conversion to AoH into this …

Re: Keyed list in perl
by jettero (Monsignor) on Mar 13, 2007 at 14:54 UTC

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://604499]
Approved by GrandFather
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others exploiting the Monastery: (5)
As of 2024-04-26 09:13 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found