Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

Converting Bracketted String (Newick's) into Array of Array

by neversaint (Deacon)
on Sep 04, 2008 at 06:02 UTC ( #708929=perlquestion: print w/replies, xml ) Need Help??

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

Dear Masters,
How can I convert the following string
my $str = "((mouse,rat),(human,chimp))"; my $str2 = "(mouse,(human,chimp))";
into this data structure
my $aoa = [['mouse','rat'],['human','chimp']]; my $aoa2 = ['mouse',['human','chimp']];
The following code of mine doesn't work:
my $str = "((mouse,rat),(human,chimp))"; $str =~ s/\(/\[/g; $str =~ s/\)/]/g; print "$str\n"; my $aoa = eval($str);


---
neversaint and everlastingly indebted.......

Replies are listed 'Best First'.
Re: Converting Bracketted String (Newick's) into Array of Array
by ikegami (Pope) on Sep 04, 2008 at 06:15 UTC

    Didn't you check $@ to see what error eval found? You forgot about quoting.

    for ($str) { s/\\/\\\\/g; s/'/\\'/g; s/\(/['/g; s/\)/']/g; s/,/','/g; }

    Update: Bah, that's buggy, but you get the idea. I'm not gonna fix it, cause it's more effort making this work with eval EXPR than developing a safer solution (i.e. one that doesn't use eval EXPR).

Re: Converting Bracketted String (Newick's) into Array of Array
by psini (Deacon) on Sep 04, 2008 at 11:10 UTC

    Try using this:

    use strict; use warnings; use Data::Dumper; my $string="((mouse,rat),(human,chimp))"; my $tree=[]; die "Invalid char in input string" if $string !~ /^[(),\w]+$/; my @tokens=$string=~/(\(|\)|,|\w+)/g; my @stack=($tree); foreach (@tokens) { if ($_ eq '(') { my $new=[]; push(@{$stack[@stack-1]},$new); push(@stack,$new); } elsif ($_ eq ')') { die "Mismatched ')'" if @stack < 2; pop(@stack); } elsif ($_ ne ',') { push(@{$stack[@stack-1]},$_); } } die "Mismatched '('" if @stack != 1; $tree=$tree->[0]; print Dumper($tree);

    Updated: added validity check on input string.

    Rule One: "Do not act incautiously when confronting a little bald wrinkly smiling man."

Re: Converting Bracketted String (Newick's) into Array of Array
by busunsl (Vicar) on Sep 04, 2008 at 06:22 UTC
    I'd go for something like this (untested):

    # convert parens to brackets $str =~ tr/()/[]/; # quotes $str =~ s/(\w+)/'$1'/g; # eval my $aoa; $eval = '$aoa = ' . $str; eval $eval;
Re: Converting Bracketted String (Newick's) into Array of Array
by betterworld (Curate) on Sep 04, 2008 at 14:50 UTC

    Sometimes you think "this looks like a perfect task to use these cool RE features," but then you end up with something that does not look as beautiful as planned:

    use strict; use warnings; use 5.010; my $str = '((mouse,rat),(human,chimp))'; my $str2 = '(mouse,(human,chimp))'; my @buffers; for ($str, $str2) { @buffers = ([]); m[ ^ ( (?: (\w+) # This serves only to get out fast if we parse # something bad (e.g. where closing parens are # missing) (*PRUNE) (?{ push @{$buffers[-1]}, $2; }) | \( (?{ push @{$buffers[-1]}, my $new = []; push @buffers, $new; }) (?1) (?{ pop @buffers; }) \) ) (?: , (?1) )? ) \z ]x ? do { use Data::Dumper; print Dumper $buffers[0]; } : do { warn "no match: $_\n"; }; }

    I look forward to suggestions on how to simplify this code ;)

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (2)
As of 2020-02-23 08:39 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    What numbers are you going to focus on primarily in 2020?










    Results (102 votes). Check out past polls.

    Notices?