in reply to Re^2: Building a UNIX path from Irritating data
in thread Building a UNIX path from Irritating data
I replaced everything after the second open with this:
my %parents_of; my $parentid; while ( my $line = <FFINFO> ) { if ($line =~ /^Folder (\d{3,5})\s+\-\s+.*\./) { $parentid = $1; } elsif ($line =~ /\s+subfolder\s+(\S+)\s+\-\s+.*\./) { push @{ $parents_of{ $1 } }, $parentid; } } sub build_path { my $folderid = shift @_; my @parents = @{ $parents_of{ $folderid } || [] }; return @parents ? [ map { map { "$_/$folderid" } @{ build_path( +$_ ) } } @parents ] : [ $folderid ]; } foreach my $k (sort (keys (%folders))) { $folderpaths{$k} = build_path($k); print "$k => $_\n" for @{ $folderpaths{$k} }; }
The highlights of the changes are:
- I read the subfolders file only once.
- I store the subfolders data in a %parents_of hash of arrays, which maps each folder ID to the folders that have it as a subfolder.
- In build_path, I use the hash of arrays instead of iterating over the whole subfolders file. It's still recursive.
- Since build_path returns an array reference now, the output loop has to iterate its contents.
For the ID that you pointed out, the new output is:
3053 => 100/3051/3053 3053 => 100/3057/3053 3053 => 100/3063/3053 3053 => 100/3066/3053
The new code produces all the output of the old code plus another 1108 lines, and it runs in less than 1 second while the original takes about 220 seconds.
I hope this helps.
In Section
Seekers of Perl Wisdom