Played with your code, the way you using pop is a big problem, not recursive.
In those display functions, I don't think you want to change the content of the hash being displayed, but pop will remove those elements from your hash (to be more precise, elements are removed from those array refs, which are elements of your hash).
When you try to display again, those elements are gone ;-).
Made some little changes here and there, the main points are:
- Removed pops, instead just use foreach
- modified the sequence you call sub routines
use strict;
use warnings;
my ($curr_string, $in, $select, %immed_child, $all_descends);
load_hashes();
process_input();
sub process_input{
while(1){
print qq(enter concept name or "Q" to quit\n);
chomp($in = <>);
exit() if $in =~ /^\s*q\s*$/i;
$in =~s/^\s*(\w+)\s*$/$1/;
# still need to check if a valid concept
print qq(enter:\n"A" for all descendents,\n"I" for immediate c
+hildren\n"P" for parents\n);
chomp($select = <>);
$select =~ s/^\s*([aip])\s*$/$1/i;
print $select, "\n";
show_results();
}
}
# key: parent
# val: list of immediate children
sub load_hashes{
my ($child, $par);
while(<DATA>){
chomp;
($child, $par) = split/\t/;
push @{$immed_child{$par}}, $child;
}
}
#global hash needed to exchange vals w other subs
sub get_descends{
my $root = shift;
$all_descends->{$root}++ if $root;
foreach my $immed (@{$immed_child{$root}}) {
get_descends($immed);
$all_descends->{$immed}++;
}
return keys %{$all_descends};
}
sub make_display_string{
my $root = shift;
my $level = shift ;
$curr_string = shift || $root;
# $curr_string = "\n". $curr_string;
$level++;
foreach my $immed (@{$immed_child{$root}}) {
$curr_string .="\n". "\t" x $level . $immed;
make_display_string($immed, $level, $curr_string);
}
#$curr_string = "\n" . $curr_string;
}
sub show_results{
$" = "\n\t";
if ($select =~ m/a/i){
print qq(\ndescendents of \n"$in":\n);
$all_descends = {};
my @descends = get_descends($in);
print "\t@descends\n";
}
elsif ($select =~m/i/i){
if (@{$immed_child{$in}}){
print qq(\nimmediate children of \n"$in":\n);
print "\t@{$immed_child{$in}}\n";
}
else{
print "no immediate children of $in";
}
}
elsif ($select =~ m/p/i){
print "working on this\n";
}
}
__DATA__
vehicle taxonomy
exercise device taxonomy
computer topic taxonomy
automobile vehicle
ford automobile
chevy automobile
bike vehicles
bike exercise device
jumprope exercise device
treadmill exercise device
perl computer topic
database computer topic
Update1:
Actually there are other problems, for example, when I try to get all descendents of bike, it displayed a list for me, when bike even does not have immediate descedent.
Your get_descendent function is changing the content of global %all_descents each time it is called. that should not happen.
This is a good lesson, why one should put variables into smaller scopes.
I didn't fix this, you can try to fix it.
Update2:
I really should leave this to you, but just cannot avoid touching your code.
Now I changed your all_descents from hash to hash ref. And added one line to reset $all_descents to {} each time before you get into the recursive. This fixes the problem I described in update1.
Still there is one thing I consider as a bug (of course there could be more bugs, I am not throughly testing this ;-). It is that, when I try to display all descendents of bike, it would take bike as a descendents of itself, which I don't think right.
Give you a hint, the problem is the second line of get_descent(), now I really leave this to you.
One thing I did bad is that I fixed some problems without modify the style of your code. This should not lead you to think that you can continue with your style. I am absolutely serious ;-), that you better use variables with smaller scopes.
Update3:
jjohhn, I have read your reply.
- There is no problem with your hash, the only reason I changed it to hash ref is that, I want to do $hash = {} to reset. Well, actually I could do a %hash = ().
- I didn't say your subroutines are not subroutines ;-) What I said is that I changed the when/where to call your subroutines, for example, now it only reads the file once...
Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
Read Where should I post X? if you're not absolutely sure you're posting in the right place.
Please read these before you post! —
Posts may use any of the Perl Monks Approved HTML tags:
- a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
| |
For: |
|
Use: |
| & | | & |
| < | | < |
| > | | > |
| [ | | [ |
| ] | | ] |
Link using PerlMonks shortcuts! What shortcuts can I use for linking?
See Writeup Formatting Tips and other pages linked from there for more info.