Reputation: 137
Does anyone have any experience of using Tree::Simple
or putting data into a tree in Perl?
Say I have the following CSV file of data:-
Bob, Bill, Ben, Brett
Bob, Bill, Brian
Bob, John, Jim
Alice, John, Jill, Jane
Alice, Jean
Alice, Janet, Brian
I would like to convert it into a tree structure in order to obtain the following:
1, Bob
2, Alice
1.1, Bill
1.1.1, Ben
1.1.1.1, Brett
1.1.2, Brian
1.2, John
1.2.1, Jim
2.1, John
2.1.1, Jill
2.1.1.1, Jane
2.2, Jean
2.3, Janet
2.3.1, Brian
I have looked at Tree::Simple
and know that if I can get the data into a tree I can use Tree::Parser
to output it with the correct numbering.
What I would like is an an example of how I could input the data line by line. I could start by reading each line of the file into an array, and adding $array[0]
in as the first child - e.g.
$tree->addChildren(Tree::Simple->new($array[0]));
What I don't know how to do is:
Check whether there already is a child with that name in the tree, so that I don't add say Bob in twice.
Find the correct parent for each child so that say Jill is entered as a child of the John who is the child of Alice, not the child of Bob
I would much appreciate some help on this problem. I've been working on it for 4 days and cannot get there. If Tree::Simple
is not the best way of doing this, perhaps there is another way?
Upvotes: 0
Views: 2182
Reputation: 126742
This program reads the sample data you have shown from the DATA
filehandle and appears to do what you need.
It keeps track of all the nodes in the tree by putting them in a hash indexed by each node's value. Every time a value appears in the input file the hash is checked to see if a node for it already exists. If not then a new tree node is created and added to the hash. Either way the node is used as the parent for the next value on the same line.
There is no check for consistency of the data, and it is assumed that every node has at most one parent. If a value appears a second time in the data file beneath a different parent name the new association is ignored.
use strict;
use warnings;
use Tree::Simple;
use Tree::Parser;
my %nodes;
my $root = Tree::Simple->new('root');
while (<DATA>) {
my $parent = $root;
for my $name (split) {
$name =~ tr/,//d;
$nodes{$name} = Tree::Simple->new($name, $parent) unless $nodes{$name};
$parent = $nodes{$name};
}
}
my $tp = Tree::Parser->new($root);
$tp->useDotSeparatedLevelFilters;
print "$_\n" for $tp->deparse
__DATA__
Bob, Bill, Ben, Brett
Bob, Bill, Brian
Bob, John, Jim
Alice, John, Jill, Jane
Alice, Jean
Alice, Janet, Brian
output
1 Bob
1.1 Bill
1.1.1 Ben
1.1.1.1 Brett
1.1.2 Brian
1.2 John
1.2.1 Jim
1.2.2 Jill
1.2.2.1 Jane
2 Alice
2.1 Jean
2.2 Janet
Upvotes: 1