2017-01-26 3 views
2

je dois déterminer le niveau hiérarchique pour afficher un arbre, je ne ai pas besoin de lier des relations au moment, j'ai une liste d'objets comme suit:Déterminer la hiérarchie entier de parent de champ C#

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

Je dois définir l'entier hierarchyLevel en fonction de son niveau de ligne. La hierarchyParent var contient l'ID de son parent. Je ne sais pas quelle serait la largeur de chaque colonne ni combien de lignes, donc elle doit être dynamique avec l'entier de niveau hiérarchique croissant ou décroissant. Jusqu'à présent, j'ai été en mesure de déterminer la rangée supérieure, mais je ne sais pas comment continuer, toute aide serait appréciée! Jusqu'à présent:

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; 
} 
+0

Type de propriétéParent n'existe pas dans votre base de données. – AFract

+0

Désolé! renommé une variable et oublié de mettre à jour une partie de mon code, fera maintenant –

Répondre

3

Voici un essai rapide des échantillons de données et les appels récursifs:

La partie utile est est en méthode AssignChild.

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); }); 
} 

Il peut probablement être optimisé mais cela devrait fonctionner.

+0

PS: objects.Dump() vient de LinqPad, il est juste utilisé pour afficher rapidement la liste des résultats. – AFract

2

Je suggère de faire quelque chose comme ceci:

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)); 
} 

Bien sûr, vous devez intégrer dans vos classes afin que vous puissiez éventuellement remplacer les arguments par les membres de la classe. Notez également qu'une vérification d'erreur peut être requise. C'est juste pour vous donner une idée d'un algorithme.

Pour les performances, je suggère un mécanisme de mise en cache. Comme l'initialisation hierarchyLevel à -1 et en utilisant la modification suivante:

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)); 
} 

Bien sûr, cela nécessiterait tous les résultats invalidant mises en cache lorsque vous voulez recalcule après un changement dans la structure de votre hiérarchie.