2015-12-23 1 views
0

Предположим, я хотел перечислить файлы каталога & итеративно таким образом, чтобы сначала выдавались внутренние каталоги и файлы.Перечисление каталогов итеративно в «почтовом ящике»

Если вы должны были выполнить это перечисление в цикле foreach с функциями: DeleteFile и DeleteEmptyDirectory, это не должно терпеть неудачу, потому что первые внутренние элементы выдаются.

Теперь, конечно, можно было бы сделать это (псевдокод):

func(Directory dir) 
    foreach (var f in dir.EnumerateFileSystemInfos()) 
     if (f is FileInfo) 
      yield return f; 
     else 
      foreach (var item in func(f)) 
       yield return item; 

    yield return dir; 

Но есть много отходов ассигнований на счетчиками.

Можно также использовать два стека и «собрать» все каталоги вместе, а затем просто вытаскивать элементы, но это слишком много памяти и не сбалансирует время MoveNext.

Любые идеи о том, как это сделать эффективно, не тратя слишком много места?

+0

Этот код не делает не идти через файлы в подкаталогах. Вы не хотите просматривать файлы в подкаталогах? –

+0

@Yacoub Massad Я бы сказал «нет», он указывает «итеративно» –

+0

Извините, я хочу просматривать файлы в подкаталогах, я должен удалить этот фрагмент кода, не пытаюсь переходить через него рекурсивно, потому что я создаю state machine, это был псевдокод более или менее, но да, это было неправильно – hl3mukkel

ответ

1

В духе DRY принципе, я хотел бы использовать функцию из моего ответа на How to make an IEnumerable of values of tree nodes?

public static class TreeHelper 
{ 
    public static IEnumerable<T> Traverse<T>(T node, Func<T, IEnumerable<T>> childrenSelector, bool preOrder = true) 
    { 
     var stack = new Stack<IEnumerator<T>>(); 
     var e = Enumerable.Repeat(node, 1).GetEnumerator(); 
     try 
     { 
      while (true) 
      { 
       while (e.MoveNext()) 
       { 
        var item = e.Current; 
        var children = childrenSelector(item); 
        if (children == null) 
         yield return item; 
        else 
        { 
         if (preOrder) yield return item; 
         stack.Push(e); 
         e = children.GetEnumerator(); 
        } 
       } 
       if (stack.Count == 0) break; 
       e.Dispose(); 
       e = stack.Pop(); 
       if (!preOrder) yield return e.Current; 
      } 
     } 
     finally 
     { 
      e.Dispose(); 
      while (stack.Count != 0) stack.Pop().Dispose(); 
     } 
    } 
} 

использовать его для Вашего случая будет что-то вроде этого

var directory = new DirectoryInfo(path); 
var result = TreeHelper.Traverse<FileSystemInfo>(directory, fsi => 
    fsi is DirectoryInfo ? ((DirectoryInfo)fsi).EnumerateFileSystemInfos() : null, 
    preOrder: false) 
+0

Красиво сделано! :) Спасибо – hl3mukkel

 Смежные вопросы

  • Нет связанных вопросов^_^