Perl: используя Loop или Map / Grep? - PullRequest
5 голосов
/ 12 декабря 2011

Я пишу программу для перехода по дереву каталогов (да, я знаю о File :: Find, но я пишу замену).

В моей программе я делаю readdir для всего каталога и помещаю его в список. Мне нужно сделать две вещи:

  1. Удалить . и .. из списка
  2. Добавить имя текущего каталога в каждом файле.

Я могу сделать это с помощью цикла, или я могу использовать map и 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;

А как насчет объединения grep и map?

 opendir $dir_fh, $cwd;
 my @dir_stack = readdir $dir_fh;;
 @dir_stack = grep { !/^\.{1,2}$/ && {$_ = "$cwd/$_"} } @dir_stack;
 push @stack, reverse @dir_stack;

Я хочу, чтобы мой код был читаемым на следующей неделе, когда я посмотрю на него и попытаюсь выяснить, что происходит. Мне также нужен мой код, чтобы быть эффективным.

Ответы [ 3 ]

7 голосов
/ 12 декабря 2011

Изменение $_ в grep?Тьфу!А что с использованием анонного хеш-конструктора?

@dir_stack = grep { !/^\.{1,2}$/ && {$_ = "$cwd/$_"} } @dir_stack;

должно быть

@dir_stack = map { /^\.\.?\z/ ? () : "$cwd/$_" } @dir_stack;

Но я лично считаю, что использование карт и grep более читабельно, чем их объединение.

push @stack,
   reverse
    map "$cwd/$_",
     grep !/^\.\.?\z/,
      readdir $dh;

Потребность в reverse довольно странная, и здесь она гораздо более заметна, чем прятаться как unshift, так что это еще один бонус.

2 голосов
/ 12 декабря 2011

Чтобы сделать ваш код более читабельным, вам нужно просто добавить еще одну строку:

# exclude '.' and '..', and prepend dir name to each elem in @dir_stack

: -)

1 голос
/ 13 декабря 2011

Звучит так, как будто вы хотите вместо glob.Хотя я считаю, что это исключит все файлы, начинающиеся с . (т.е. скрытые файлы), а не только . и ...И, конечно же, в пути не должно быть пробелов.

my @stack = glob "$dir_fh/*";

Он будет возвращать столько же путей, сколько вы его кормите.

...