2012-02-23 14 views
9

MyClass składa IDParentID i List<MyClass> jak Children(ID/ParentID) wykaz do hierarchiczną listę

Mam listę MyClass jak ten

ID ParentID 
1 0 
2 7 
3 1 
4 5 
5 1 
6 2 
7 1 
8 6 
9 0 
10 9 

wyjściowego (lista hierarchiczna) jako List<MyClass>

1 __ 3 
|__ 5__ 4 
|__ 7__ 2__ 6__ 8 
    |__ 11 

9 __10 

Jaki jest najprostszy sposób osiągnięcia tego w linq?
PS: ParentID nie klasyfikowane

Edit:
My try:

class MyClass 
{ 
    public int ID; 
    public int ParentID; 
    public List<MyClass> Children = new List<MyClass>(); 
    public MyClass(int id, int parent_id) 
    { 
     ID = id; 
     ParentID = parent_id; 
    } 
} 

zainicjować przykładowe dane i starają się dotrzeć do danych hierarchicznych

List<MyClass> items = new List<MyClass>() 
{ 
    new MyClass(1, 0), 
    new MyClass(2, 7), 
    new MyClass(3, 1), 
    new MyClass(4, 5), 
    new MyClass(5, 1), 
    new MyClass(6, 2), 
    new MyClass(7,1), 
    new MyClass(8, 6), 
    new MyClass(9, 0), 
    new MyClass(10, 9), 
    new MyClass(11, 7), 
}; 

Dictionary<int, MyClass> dic = items.ToDictionary(ee => ee.ID); 

foreach (var c in items) 
    if (dic.ContainsKey(c.ParentID)) 
     dic[c.ParentID].Children.Add(c); 

jak widać, wiele pozycje Nie chcę jeszcze w słowniku

+0

Jaki rodzaj struktury danych powinny być wyjście? – Jon

+0

@ Jon: Proszę odnieść się do mojego zaktualizowanego pytania –

+0

Ale "Lista" nie jest hierarchiczną strukturą danych. Mówiąc inaczej, w jaki sposób proponujecie zamienić 'List' na zobrazowane drzewo? – Jon

Odpowiedz

13

Dla danych hierarchicznych potrzebujesz rekursji - pętla foreach nie będzie wystarczająca.

items to ta sama lista, której używasz. Zwróć uwagę, jak metoda sama wywołuje metodę SetChildren. To właśnie buduje hierarchię.

+1

Jest to mniej wydajne niż oryginalny kod OP. Metoda słownikowa jest o wiele lepsza. –

+0

Przyjemny użytkownik347805, działa dla mnie – Shailesh

+0

To jest fajna sztuczka .. !! to też działa dla mnie .. !! –

32

Rekursja nie jest tutaj konieczna, jeśli przed filtrowaniem budowane są relacje nadrzędny-podrzędny. Ponieważ członkowie listy pozostają tymi samymi obiektami, o ile powiązacie każdego członka listy z jego bezpośrednim potomkiem, wszystkie niezbędne relacje zostaną zbudowane.

Można to zrobić w dwóch wierszach:

items.ForEach(item => item.Children = items.Where(child => child.ParentID == item.ID) 
              .ToList()); 
List<MyClass> topItems = items.Where(item => item.ParentID == 0).ToList(); 
+0

Nie myślałem o tym. Masz rację. Tworzenie hierarchii nie wymaga rekursji, wykonuje tylko ** traversing **. – user347805

+0

Traversing też nie. :) – DiVan

+0

Po prostu użyłem tego dla podobnego projektu. Piękne rozwiązanie i wydajne. –

1

mam wymaganych takiej funkcjonalności i porównanie obu metod i znaleźć sposób 2-cia jest szybsze niż 1 :), teraz w moich kart baz danych lub rejestrów są ograniczone, ale Pierwsza metoda wykonania 4-krotnie więcej czasu.

może to pomóc tym, którzy są świadomi czasu.

1 metoda


public JsonResult CardData() 
    { 
     var watch = System.Diagnostics.Stopwatch.StartNew(); 
     OrgChartWithApiContext db = new OrgChartWithApiContext(); 

     var items = db.Cards.ToList(); 
     Action<Card> SetChildren = null; 
     SetChildren = parent => { 
      parent.Children = items 
       .Where(childItem => childItem.ParentId == parent.id) 
       .ToList(); 

      //Recursively call the SetChildren method for each child. 
      parent.Children 
       .ForEach(SetChildren); 
     }; 

     //Initialize the hierarchical list to root level items 
     List<Card> hierarchicalItems = items 
      .Where(rootItem => !rootItem.ParentId.HasValue) 
      .ToList(); 

     //Call the SetChildren method to set the children on each root level item. 
     hierarchicalItems.ForEach(SetChildren); 
     watch.Stop(); 
     var timetaken = watch.ElapsedMilliseconds; 

     return new JsonResult() { Data = hierarchicalItems, ContentType = "Json", JsonRequestBehavior = JsonRequestBehavior.AllowGet }; 
    } 

metoda 2


public JsonResult Card2Data() 
    { 
     var watch = System.Diagnostics.Stopwatch.StartNew(); 
     OrgChartWithApiContext db = new OrgChartWithApiContext(); 
     var items = db.Cards.ToList(); 
     List<Card> topItems = items.Where(item => !item.ParentId.HasValue).ToList(); 
     topItems.ForEach(item => item.Children = items.Where(child => child.ParentId == item.id).ToList()); 
     watch.Stop(); 
     var timetaken = watch.ElapsedMilliseconds; 
     return new JsonResult() { Data = topItems, ContentType = "Json", JsonRequestBehavior = JsonRequestBehavior.AllowGet }; 
    } 
Powiązane problemy