Home > Back-end >  Make function dynamic / use Iteration / Make DRY
Make function dynamic / use Iteration / Make DRY

Time:12-02

I want to make this function dynamic/Dry rather than having to do multiple loops, do one loop /recursively

step1: The function receives a path
from that path it creates a Dir Model for the parent directory,
if the parent has sub directories, it adds them as models, to the parent subdirectory list,

step2: for each of the sub directories it repeats what it did in step 1, with the child being the parent to its sub directories if it has them,

this should repeat as long as a subdirectory to a parent has subdirectories,

finally, it returns the main Directory with its sub directories, as models with their own subdirectory models 

public string RepoAsJson(string repoPath)
{
    string path = @"C:\parentDir\subDir\subSubDir";
    string[] parentDir = Directory.GetDirectories(path);
    RepoDirModel model = new RepoDirModel();

    foreach (string dir in parentDir){
           RepoDirModel model1 = new RepoDirModel();
           model1.Name = rket.Split(Path.DirectorySeparatorChar).Last();
           model.SubDirectories.Add(model1);

          foreach (string sub in Directory.GetDirectories(rket))
            {
                RepoDirModel model2 = new RepoDirModel();
                model2.Name = sub.Split(Path.DirectorySeparatorChar).Last();
                model1.SubDirectories.Add(model2);

                foreach (string subSub in Directory.GetDirectories(sub))
                {
                    RepoDirModel model3 = new RepoDirModel();
                    model3.Name = subSub.Split(Path.DirectorySeparatorChar).Last();
                    model2.SubDirectories.Add(model3);
                }
            }
        }
        return JsonSerializer.Serialize(model);
}

Remove nested loops / use Iteration / Make function dynamic

CodePudding user response:

Since this seems to be some sort of course work / homework / training (maybe?), I am not going to post a working solution, but rather give you some hints.

First of all: What is the common "thing" your existing code does?

  • It gets the list of subdirectories from a specific path string and adds those into a tree structure.

That's it. So the first thing you might want to do is "extract" this functionality into a function or method, that only works on its parameters (no outside fields, "global vars" or something like that). You pass it the node to expand and the path to analyse and it will take care of one step.

Now, if you want to go into recursion, you need some additional things:

  • Do you want to go deep first or wide first?
  • When do you stop?

The second question is rather easy here: If there are no children (i.e. subdirectories) of the current subject, we are done - no further recursion.

The answer to the first one may not be so relevant in this setting, but think about it anyway. If for example you are looking for a specific leaf or node in the tree it might be relevant if it is more probable that you will find it quicker going deep first or go level by level.

But anyway: If you want to go deep first, you'd do something like this (Pseudo code)

RecursiveMethod( Element parent, ModelNode parentNode )
{
     foreach (child of parent)
     {
         newNode = AddToModel(parentNode, child)
         RecursiveMethod( child, newNode ) // <-- Note: Recursion IN the loop
     }
}

And if you want to go wide something like

RecursiveMethod( List<Element> parents, Model m )
{
     newParents = new List<Element>();
     foreach( parent in parents ) 
     {
         foreach (child of parent)
         {
             AddToModel(m, parent, child)
             newParents.Add(child);
         }
     }
     // Note: Recursion AFTER the loop - in some cases it may even happen _before_
     if( newParents.Length > 0 ) RecursiveMethod( newParents, m ); 
}

If you want an iterative solution, you have again those two questions, you just do a little different:

// you need some sort of datastructure, for "width first" we can use a FIFO queue
queue = new Queue(); // Not _the_ .NET Queue, just a FIFO for demo
// we start with the root...
queue.Enqueue( path );

// Then you do that one step as long as there is something in the queue
while( queue.Length > 0 )
{
     current = queue.Dequeue(); // Get the first element in queue
     foreach( child of current ) // No child -> no new elements in queue, length decreases
     {
         // If there are children => 
         // Do what you need to do
         InsertIntoModel(child); // Whatever that means in particular
         // and put them into the queue for later processing
         // queue length increases
         queue.Enqueue(child);
     }
}

If you want to go deep first, you can chose another mode of insertion and/or a different data structure. (For example a Stack, that is LIFO, creating width-first behavior)

  • Related