Good lambda expression or best way to reduce for each loop

I want to get subfolders of the root folder. And I can get it through the code below. But there is a problem when there is a subfolder in a subfolder, and I find it by recording a second for each cycle. But what if the second subfolder has a subfolder below it. So there will be infinte for each cycle, so I have to overcome it. Any help deserves. 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); } } 
+4
source share
5 answers

Ideal 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 recursive lambdas , but they are too complex.

+10
source

Is there a good reason why the dictionary is not at the field level, and does not pass it through a 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); } } 
+1
source

Here are two additional samples using labdas. The first uses a function declared locally to recursion over elements (in this case DirectoryInfos), 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))); } } 
0
source

Here is an example of how to write a recursive traversal using a recursive lambda expression and using the 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 in its definition. This is not a problem because it will be used after its initialization, but the C # compiler requires us to declare this earlier.

The body of the lambda expression calls SelectMany , which calls the given lambda expression for each element of the input sequence and combines all the returned sequences - our lambda returns the current dir directory and then all the recursively computed dir subdirectories.

This is probably not particularly effective, but it definitely shows how you can use lambda functions to write short code (it could be optimized, however, the F # libraries do this because it is a more common template 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 similar to C # iterators. yield corresponds to yield return , and yield! gives all the elements of a sequence (it's like iterating over it using foreach and providing individual elements using yield return , but more efficient).

0
source

I have done it. Here is 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; } 
0
source

Source: https://habr.com/ru/post/1301810/


All Articles