Reputation: 1807
I want to get sub folders of a root folder. And i am able to get it through the below code. But has a issue when the sub folder has a sub folder in it and i over come it writing a second for each loop. But what if the second sub folder has a sub folder under it. So there will be an infinte for each loop, so i have to overcome it. Any help is worthfull.Thanks in advance.
foreach (Folder.Folder folder in FolderService.Instance.GetSubFolders(userContext, folderID))
{
folderById.Add(folder.FolderID, folder);
foreach (Folder.Folder sfolder in FolderService.Instance.GetSubFolders(userContext, folder.FolderID))
{
folderById.Add(sfolder.FolderID, sfolder);
}
}
Upvotes: 4
Views: 1459
Reputation: 1807
I got it done . Here's the code.
private List<Folder.Folder> GetAllF(AbstractUserContext userContext, string folderID)
{
List<Folder.Folder> listFold = new List<Folder.Folder>();
foreach (Folder.Folder folder in FolderService.Instance.GetSubFolders(userContext, folderID))
{
listFold.Add(folder);
listFold.AddRange(GetAllF(userContext,folder.FolderID));
}
return listFold;
}
Upvotes: 0
Reputation: 2053
Is there a good reason for the dictionary to not be at field level rather than passing it through the recursive call?
Dictionary<string, int> folderById = new Dictionary<string,int>();
public void Start()
{
// code for initial context + folder id
RecurseFolders(userContext, folderId);
}
public void RecurseFolders(string userContext, int folderId)
{
foreach (Folder.Folder folder in FolderService.Instance.GetSubFolders(userContext, folderID)) {
folderById.Add(folder.FolderID, folder);
RecurseFolders(userContext, folder.folderId);
}
}
Upvotes: 1
Reputation: 243061
Here is an example how to write recursive traversal using recursive lambda expression and using SelectMany
method from LINQ:
Func<string, IEnumerable<string>> folders = null;
folders = s =>
Directory.GetDirectories(s).SelectMany(dir =>
Enumerable.Concat(new[] { dir }, folders(dir)));
foreach (var d in folders("C:\\Tomas\\Writing\\Academic"))
Console.WriteLine(d);
The first line declares the lambda expression in advance, because we use it later inside its definition. This is not a problem, because it will be used after it has been initialized, but the C# compiler requires that we declare it earlier.
The body of the lambda expression calls SelectMany
, which calls the given lambda expression for each element of the input sequence and concatenates all returned sequences - our lambda returns the current directory dir
and then all recursively calculated subdirectories of dir
.
This is probably not particularly efficient, but it definitely shows how you can use lambda functions to write short code (it could be optimized however, F# libraries do that, because this is more common pattern in F#).
Just for comparison, the same thing in F# looks like this:
let folders s = seq {
for dir in Directory.GetDirectories(s)
yield dir
yield! folders dir }
The code uses sequence expressions which are like C# iterators. yield
corresponds to yield return
and yield!
yields all elements of a sequence (it is like iterating over it using foreach
and yielding individual elements using yield return
, but more efficient).
Upvotes: 0
Reputation: 16926
Here are two additional samles using labdas. The first uses a function declared locally to recurse over the items (DirectoryInfos in this case) and the second uses an instance method.
class Program
{
static void Main(string[] args) {
string path = @"d:\temp";
Func<DirectoryInfo, IEnumerable<DirectoryInfo>> func = null;
func = (folder) => {
return new[] { folder }.Concat(folder.GetDirectories().SelectMany(x => func(x)));
};
IEnumerable<DirectoryInfo> dirs = (new DirectoryInfo(path)).GetDirectories().SelectMany(x => func(x));
IEnumerable<DirectoryInfo> dirs2 = GetSubDirs(new DirectoryInfo(path));
}
public static IEnumerable<DirectoryInfo> GetSubDirs(DirectoryInfo dir) {
yield return dir;
foreach (var subDir in GetSubDirs(dir)) yield return subDir;
}
// method 2 even shorter
public static IEnumerable<Directory> GetSubDirs2(DirectoryInfo dir) {
return new[] { dir }.Concat(dir.GetDirectories().SelectMany(x => GetSubDirs2(x)));
}
}
Upvotes: 0
Reputation: 115769
Perfect place for recursion:
... TraverseFolder(rootFolderID, userContext)
{
var folderById = new ...;
TraverseFolder(folderById, rootFolderID, userContext);
return folderById;
}
void TraverseFolder(folderById, folderID, userContext)
{
var folders = FolderService.Instance.GetSubFolders(userContext, folderID);
foreach(var folder in folders)
{
folderById.Add(folder.FolderID, folder);
TraverseFolder(folder.FolderID);
}
}
Theoretically, you can have recursive lambdas, but they are waay too complicated.
Upvotes: 10