简体   繁体   中英

Determine Hierarchy Integer from Parent Field C#

I need to determine the hierarchy level to display a tree, I don't need to link relationships at the moment, I have a list of objects as follows:

public class ObjectData
{
    public string ID;
    public string hierarchyParent;
    public int hierarchyLevel;
}

I need to set the hierarchyLevel integer based on its row level. The hierarchyParent var contains the ID of its parent. I don't know how wide each column would be nor how many rows, so it needs to be dynamic with the hierarchy level integer either ascending or descending. So far, I have been able to determine the top row but am unsure how to continue, any help would be appreciated! So far:

List<ObjectData> Sort(List<ObjectData> objectToBeSorted){
    List<ObjectData> returnlist = new List<ObjectData>();
    string topObject = null;
    foreach(ObjectData obj in objectToBeSorted)
    {
        if(obj.hierarchyParent == null){
            topObject = obj.ID;
            obj.hierarchyLevel = 1; 
        }
    }
    foreach(ObjectData obj in objectToBeSorted)
    {
        if(obj.hierarchyParent == topObject){

        }           
    }



    return returnlist;
}

Here's a quick try with sample data and recursive calls :

The useful part is is in AssignChild method.

public class ObjectData
{
    public string ID;
    public string hierarchyParent;
    public int hierarchyLevel;
}

void Main()
{

    var objects = new List<ObjectData>() { 
    new ObjectData() { ID = "Obj12", hierarchyParent = null }, 
    new ObjectData() { ID = "Obj5", hierarchyParent = "Obj12" }, 
    new ObjectData() { ID = "Obj9", hierarchyParent = "Obj12" },
    new ObjectData() { ID = "Obj7", hierarchyParent = "Obj5" },
    new ObjectData() { ID = "Obj99", hierarchyParent = "Obj58" },
    new ObjectData() { ID = "Obj58", hierarchyParent = "Obj5" } };

    ObjectData top = objects.Find(p => p.hierarchyParent == null);
    top.hierarchyLevel = 1;

    AssignChild(objects, top);

    objects.Dump();
}

void AssignChild(List<ObjectData> all, ObjectData parent)
{
    var child = all.FindAll(o => o.hierarchyParent == parent.ID);
    child.ForEach(c => { c.hierarchyLevel = parent.hierarchyLevel +1; AssignChild(all, c); });
}

It can probably be optimized but it should work.

I suggest doing something like this:

public int GetHierarchyLevel(ObjectData obj, IEnumerable<ObjectData> allObjects)
{
    if(obj.hierarchyParent == null)
        return 1;
    else
      return 1 + GetHierarchyLevel(allObjects.First(o=>o.ID == obj.hierarchyParent));
}

Of course, you should integrate this into your classes so that you can possibly replace the arguments by class members. Also, please notice that some error checking may be required. It is just meant to give you an idea of an algorithm.

For performance, I suggest a caching mechanism. Like initializing hierarchyLevel to -1 and using the following modification:

public int GetHierarchyLevel(ObjectData obj, IEnumerable<ObjectData> allObjects)
{
    if (obj.hierarchyLevel != -1)
        return obj.hierarchyLevel;
    if(obj.hierarchyParent == null)
        return 1;
    else
      return 1 + GetHierarchyLevel(allObjects.First(o=>o.ID == obj.hierarchyParent));
}

Of course, this would require invalidating all cached results when you want to recalculate after a change in the structure of your hierarchy.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM