2012-03-02 15 views
2

私は以前これを行う方法を知っていたと思うが、私は忘れてしまったようだ。空のディレクトリアルゴリズムを削除して再帰を排除する

私は、再帰的なアルゴリズムは、ディレクトリツリー内のすべての空のディレクトリを削除する必要があります。私は、このアルゴリズムからの再帰を排除しようとしている

static bool DeleteDirectoriesRecursive(string path) 
{ 
    var remove = true; 
    foreach (var dir in System.IO.Directory.GetDirectories(path)) 
    { 
     remove &= DeleteDirectoriesRecursive(dir); 
    } 
    if (remove &= (System.IO.Directory.GetFiles(path).Length == 0)) 
     System.IO.Directory.Delete(path); 
    return remove; 
} 

、それほどではない、すなわち(アルゴリズムを「修正」し、 the similar questionは変数removeを使用しませんが、私はそれを保ちたいと思います)。

Stack<>クラスを使用して新しい機能を開始しましたが、基本パスに戻り、サブディレクトリが決定した操作を実行する良い方法はないと思います。私は非尾の再帰を解明するのにもう少し努力が必要だと思います。

+0

1つのスタック(ILスタック)を別のスタック(あなたのもの)に置き換えたいのはなぜですか?あなたはこれから得るために何をしていますか? – zmbq

+0

ナレッジベース。誰も私が生産コードでこれを行うつもりはないと言いました。 – palswim

+0

@zmbq - それは私が考えていたものです。実際には、呼び出しスタックを使用してツリーをクロールするので、再帰の使用は非常に有効です。独自のスタックで同じことをしようとすると、コードがずっと長くなり、理解が難しくなり、パフォーマンス上の利点も得られません。 –

答えて

1

:また、ここで少しクリーナーのバージョンがあります。私はコードhereを出発点として使用しました。

  1. は再帰なしで木をクロールあまりにも信じられないほど難しいことではありません、それは私が上記にリンクされているMSDNの記事で行われます。そして、ここで私は...

    public static bool DeleteDirectories(string root) 
    { 
        bool removed = false; 
    
        var dirs = new Stack<string>(); 
        var emptyDirStack = new Stack<string>(); 
        var emptyDirs = new Dictionary<string, int>(); 
    
        if (!System.IO.Directory.Exists(root)) 
        { 
         throw new ArgumentException(); 
        } 
        dirs.Push(root); 
    
        while (dirs.Count > 0) 
        { 
         string currentDir = dirs.Pop(); 
    
         string[] subDirs; 
         try 
         { 
          subDirs = System.IO.Directory.GetDirectories(currentDir); 
         } 
         catch (UnauthorizedAccessException e) 
         { 
          Console.WriteLine(e.Message); 
          continue; 
         } 
         catch (System.IO.DirectoryNotFoundException e) 
         { 
          Console.WriteLine(e.Message); 
          continue; 
         } 
    
         if (Directory.GetFiles(currentDir).Length == 0) 
         { 
          emptyDirStack.Push(currentDir); 
          emptyDirs.Add(currentDir, subDirs.Length); // add directory path and number of sub directories 
         } 
    
         // Push the subdirectories onto the stack for traversal. 
         foreach (string str in subDirs) 
          dirs.Push(str); 
        } 
    
        while (emptyDirStack.Count > 0) 
        { 
         string currentDir = emptyDirStack.Pop(); 
         if (emptyDirs[currentDir] == 0) 
         { 
          string parentDir = Directory.GetParent(currentDir).FullName; 
          Console.WriteLine(currentDir); // comment this line 
          //Directory.Delete(currentDir); // uncomment this line to delete 
          if (emptyDirs.ContainsKey(parentDir)) 
          { 
           emptyDirs[parentDir]--; // decrement number of subdirectories of parent 
          } 
          removed = true; 
         } 
        } 
    
        return removed; 
    } 
    

    いくつかの注意事項を思いついたものです。しかし、この特定の例は、それより少し複雑です。

  2. 私はemptyDirsディクショナリにファイルが含まれていないすべてのディレクトリと、それに含まれるサブディレクトリの数を格納しています。
  3. ディレクトリが削除される順序が重要なので、逆順でemptyDirsディクショナリを実行する必要がありました(これを達成するためにLinqを使用しました)。

もっと効率的な方法があると思いますが、これはあまりにも悪くないので、私のテストではうまくいくようです。

更新日: 私は2番目のスタックのために逆の辞書を取り除きました。しかし、私はまだ高速検索のために辞書を使用しています。

+0

なぜdownvote? –

+0

あなたは 'Dictionary'の中でどんな種類の注文にも頼るべきではありません。あなたがそれらを挿入した順番でそれらを返す場合がありますが、それは必ずしも機能しないので、あなたはそれに頼るべきではありません。 – svick

+0

@svick - お役立ち情報私はちょうど逆の辞書を捨てた。 –

1

sans-recursionバージョンははるかに難しく、それほど効率的ではないので、再帰を維持することをお勧めします。私はそれなしでこの仕事をするために触発された再帰を使用しているときゲイブがStackOverflowExceptionがの可能性を言及しているので

static bool DeleteDirectoriesRecursive(DirectoryInfo d) 
{ 
    bool remove = true; 

    foreach (DirectoryInfo c in d.GetDirectories()) 
    { 
     remove &= DeleteDirectoriesRecursive(c); 
    } 

    if (remove && d.GetFiles().Length == 0) { 
     d.Delete(); 
     return true; 
    } 

    return false; 
} 
+0

それは少しクリーナーです。ただし、必要に応じて、削除を 'false'に設定する場所を見つける必要があります(' remove&=(d。GetFiles()。Length == 0) 'somewhere)。 – palswim

+0

@palswim:良い点、完了。 – Ryan

関連する問題