I’m writing a program to step through a directory tree (Yes, I know about File::Find, but I’m writing a replacement).
In my program, I’m doing a readdir on a whole directory and placing it in a list. I need to do two things:
- Remove
.and..from the list - Prepend the current directory name on each file.
I can do this with a loop, or I can use map and grep:
# Map and Grep
my @dir_stack = readdir $dir_fh;;
@dir_stack = grep { !/^\.{1,2}$/ } @dir_stack;
@dir_stack = reverse map { "$cwd/$_" } @dir_stack;
push @stack, @dir_stack;
# Read Loop
opendir $dir_fh, $cwd;
my @dir_stack;
foreach my $file (readdir $dir_fh) {
next if $file =~ /^\.{1,2}$/; #Skip "." and ".."
unshift @dir_stack, "$cwd/$file";
}
push @stack, @dir_stack;
What about combining grep and map?
opendir $dir_fh, $cwd;
my @dir_stack = readdir $dir_fh;;
@dir_stack = grep { !/^\.{1,2}$/ && {$_ = "$cwd/$_"} } @dir_stack;
push @stack, reverse @dir_stack;
I want my code to be readable next week when I look at it and try to figure out what’s going on. I also need my code to be efficient.
Modifying
$_in grep? yuck! And what’s with using an anon hash constructor?should be
But I personally find using both map and grep more readable than combining them.
The need for
reverseis rather odd, and it’s much more visible here than hiding as aunshift, so that’s another bonus.