in reply to Re: directory listing to array tree
in thread directory listing to array tree

Only 4 lines less?
use strict; use warnings; my $INDENT=' 'x2; my @aSorted=sort qw(/var/www/data/stuff /var/www /var/www/data/misc /var/logs /var/logs/data); my $aLast=[]; foreach my $sPath (@aSorted) { chomp $sPath; my @aName = split(m{/}, $sPath); for my $i (0..$#aName) { if (($#$aLast<$i) || ($aLast->[$i] ne $aName[$i])) { if ($i>1) { print '', $INDENT x ($i-1), '->'; } print $aName[$i], "\n"; } } $aLast=\@aName; }

outputs

var ->logs ->data ->www ->data ->misc ->stuff

By using the leading portions of the path as a hash key, the subscript separator variable, $; (see perlvar), you can preserve the exact ordering given by the OP. This also takes under 20 lines, excluding the strict and warnings declaration.

use strict; use warnings; my $INDENT=' 'x2; my @aUnsorted= qw(/var/www/data/stuff /var/www /var/www/data/misc /var/logs /var/logs/data); my %hVisited; foreach my $sPath (@aUnsorted) { chomp $sPath; my @aName = split(m{/}, $sPath); for my $i (0..$#aName) { my $k=join('/',@aName[0..$i]); unless ($hVisited{$k}) { if ($i>1) { print '', $INDENT x ($i-1), '->'; }; print $aName[$i], "\n"; $hVisited{$k}=1; } } }

outputs

var ->www ->data ->stuff ->misc ->logs ->data

For the OP, I don't know that language is the real winner here in getting the volume of code down. Understanding the nature of the problem itself is far more important. PHP also has a split function and str-repeat takes the place of Perl's x operator, so this code could be translated virtually as is to PHP.

Best, beth

Update: ikegami is right, I'm not actually using $; but rather the path subsegments as the hash key. See strike out above for correction.

Replies are listed 'Best First'.
Re^3: directory listing to array tree
by ikegami (Patriarch) on Sep 14, 2009 at 19:53 UTC

    Your code doesn't use $; at all. Even if you didn't realize it, it seems you discovered that $; is useless here since you can't do $h{@segs}.

Re^3: directory listing to array tree
by Fletch (Bishop) on Sep 14, 2009 at 20:48 UTC

    Yup, roughly four lines shorter reimplementing (virtually) the same approach (not counting shebangs, use strict-y pragmata, or blank lines). Not to mention things like I don't yet grok Clojure / FP well enough that I can do in it what my $t = \%tree; while( @parts ) { my $head = shift @parts; $t = ($t->{$head} ||= {}); } lets me do trivially in Perl, or a better way than (apply str (repeat indent " ") to do " " x $indent.

    The Perl version is certainly much "slimmer" than my Clojure (and less . . . "chatty"? "visually cluttered"?) at roughly half the number of characters:

    $ wc * 44 152 1258 tree.clj 42 112 741 tree.plx 86 264 1999 total

    Also the OP had said they were trying to build a tree and traverse it; your above approach doesn't give a data structure that can be manipulated afterwards or walked multiple times (not that it's not shorter and yours preserves the original ordering (unlike mine), just that's what I read the OP as looking for).

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.