Search code examples
c#loopsrecursiontreenested-loops

C# recursive delete children object in LiteCollection DB


I have a folder list which is store in LiteCollection. I want to create a delete function that can allow user to delete the folder from whichever level. I tested on the Delete function below, it works. However I would like to simplify the code and make the search as deep as possible, not limit to the number of foreach loop. How can I simplify the function below with recursive?

PrinterDirectory Class

public class PrinterDirectory
{
    public PrinterDirectory()
    {
        Children = new List<PrinterDirectory>();
    }

    public int Id { get; set; }
    public string Key { get; set; }
    public string Title { get; set; }

    public List<PrinterDirectory> Children { get; set; }
} 

Delete Function

LiteCollection<PrinterDirectory> _printerDirectoryCollection;
List<PrinterDirectory> mainDirList = new List<PrinterDirectory>();

mainDirList = _printerDirectoryCollection.FindAll().ToList();

var stat = "";
var key = "2-0-0";

foreach (PrinterDirectory _printerDir in mainDirList)
{
    if (_printerDir.Key.Equals(key))
    {
        _printerDirectoryCollection.Delete(dir => dir.Key.Equals(key));
        break;
    }

    if(_printerDir.Children.Count != 0)
    {
        foreach(PrinterDirectory _printerDir2 in _printerDir.Children)
        {
            if(_printerDir2.Key.Equals(key))
            {
                if(_printerDir.Children.Remove(_printerDir2))
                {
                    stat = "childnode";
                    break;
                }
            }

            if(_printerDir2.Children.Count != 0)
            {
                foreach(PrinterDirectory _printerDir3 in _printerDir2.Children)
                {
                    if (_printerDir3.Key.Equals(key))
                    {
                        if (_printerDir2.Children.Remove(_printerDir3))
                        {
                            stat = "childnode";
                            break;
                        }
                    }

                    if (_printerDir3.Children.Count != 0)
                    {
                        foreach (PrinterDirectory _printerDir4 in _printerDir3.Children)
                        {
                            if (_printerDir4.Key.Equals(key))
                            {
                                if (_printerDir3.Children.Remove(_printerDir4))
                                {
                                    stat = "childnode";
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

if(stat == "childnode")
    _printerDirectoryCollection.Update(printerDirList);

Solution

    1. Check List.Count before foreach is waste because foreach do not iterate empty Lists.

    2. Remove iterating sub-item of a List might cause the iterator to Exception; So following re-factor do not pay attention to this subject as you mention:

    I tested on the Delete function below, it works.

    It seems that these code changes and the recursive function are (or are like!) that you want:

    foreach (PrinterDirectory _printerDir in mainDirList)
    {
        if (_printerDir.Key.Equals(key))
        {
            _printerDirectoryCollection.Delete(dir => dir.Key.Equals(key));
            break;
        }
        foreach (PrinterDirectory _printerDir2 in _printerDir.Children)
        {
            if (CheckChildNodes(key, _printerDir, _printerDir2))
            {
                stat = "childnode";
                break;
            }
        }
    }
    

    The recursive function:

    private static bool CheckChildNodes(string key, PrinterDirectory parent, PrinterDirectory child)
    {
        if (child.Key.Equals(key))
        {
            if (parent.Children.Remove(child))
            {
                return true;
            }
        }
        foreach (PrinterDirectory grandchild in child.Children)
        {
            if (CheckChildNodes(key, child, grandchild))
            {
                return true;
            }
        }
        return false;
    }