Mr.Pro Mr.Pro - 9 days ago 7
C# Question

Walk folder tree without recursion c#

How to change this recursive loop with non recursive?
I know this method is easy way but i'm interested in non recursive way of this solution.

using System;
using System.IO;

namespace NonRecursion {
class NonRecursion {
static void Main() {
string createPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

string getPath = createPath + @"\folder";
GetDirsPath(getPath);

Console.ReadKey();
}

static void GetDirsPath(string getPath) {
string[] dirs = Directory.GetDirectories(getPath);

for (int i = 0; i < dirs.Length; i++) {
Console.WriteLine(dirs[i]);
GetDirsPath(dirs[i]);
}
}
}
}


Can i change only this function?

static void GetDirsPath(string getPath) {
string[] dirs = Directory.GetDirectories(getPath);

for (int i = 0; i < dirs.Length; i++) {
Console.WriteLine(dirs[i]);
GetDirsPath(dirs[i]);
}
}

Answer

How about this:

public static IEnumerable<string> AllFolders(string root)
{
    var folders = new Stack<string>();
    folders.Push(root);

    while (folders.Count > 0)
    {
        string folder = folders.Pop();
        yield return folder;

        foreach (var item in Directory.EnumerateDirectories(folder))
            folders.Push(item);
    }
}

Test code (console app):

static void Main()
{
    foreach (var dir in AllFolders("<your root folder here>"))
    {
        Console.WriteLine(dir);
    }
}

Here's an alternative approach using a List<string>:

public static IEnumerable<string> AllFolders(string root)
{
    var folders = new List<string> {root};

    while (folders.Count > 0)
    {
        string folder = folders[folders.Count - 1];
        folders.RemoveAt(folders.Count-1);
        yield return folder;
        folders.AddRange(Directory.EnumerateDirectories(folder));
    }
}

These both work the same way:

They maintain a list (or stack) of directories that have not yet been output, starting with the root directory.

The algorithms remove the topmost (stack) or last (list) directory from the stack/list and output it. Then they add all the subdirectories of that directory to the list/stack and repeat, until the list/stack is empty.

In particular, note that the List<> version is in fact merely using a List<> as a Stack<>, so it's algorithmically identical.

If you just want to make minimal changes to the GetDirsPath() method:

static void GetDirsPath(string getPath)
{
    var dirs = new List<string> { getPath };

    while (dirs.Count > 0)
    {
        string dir = dirs[dirs.Count - 1];
        dirs.RemoveAt(dirs.Count - 1);
        Console.WriteLine(dir);
        dirs.AddRange(Directory.EnumerateDirectories(dir));
    }
}