2013-07-11 11 views
7

Ich habe eine Liste von Datenstrukturen:Wie erstellt man eine Hierarchie mit Linq zum Objekt?

 public List<Personal> Personals() 
     { 
      return new List<Personal> 
       { 
        new Personal 
         { 
          Id = 0, 
          Name = "Name 0" 
         }, 
        new Personal 
         { 
          Id = 1, 
          Name = "Name 1", 
          ParentId = 0 
         }, 
        new Personal 
         { 
          Id = 2, 
          Name = "Name 2", 
          ParentId = 0 
         }, 
        new Personal 
         { 
          Id = 3, 
          Name = "Name 3", 
          ParentId = 0 
         }, 
        new Personal 
         { 
          Id = 4, 
          Name = "Name 4", 
          ParentId = 1 
         }, 
        new Personal 
         { 
          Id = 5, 
          Name = "Name 5", 
          ParentId = 1 
         }, 
        new Personal 
         { 
          Id = 6, 
          Name = "Name 6", 
          ParentId = 2 
         }, 
        new Personal 
         { 
          Id = 7, 
          Name = "Name 7", 
          ParentId = 2 
         }, 
        new Personal 
         { 
          Id = 8, 
          Name = "Name 8", 
          ParentId = 4 
         }, 
        new Personal 
         { 
          Id = 9, 
          Name = "Name 9", 
          ParentId = 4 
         }, 
       }; 
     } 

und ich möchte einen Baum bauen: zum Objekt

public List<Tree> Trees() 
      { 
       return new List<Tree> 
        { 
         new Tree 
          { 
           Id = 0, 
           Name = "Name 0", 
           List = new List<Tree> 
            { 
             new Tree 
              { 
               Id = 1, 
               Name = "Name 1", 
               List = new List<Tree> 
                { 
                 new Tree 
                  { 
                   Id = 4, 
                   Name = "Name 4" 
                  }, 
                 new Tree 
                  { 
                   Id = 5, 
                   Name = "Name 5" 
                  } 
                } 
              } 
            } 
          } 
        }; 
      } 

Wie man einen Baum mit LinQ bauen Sie? Ich habe zu verwenden, aber es ist nicht genau das funktioniert, siehe unten:

public void SomeMethod() { 
    // here you get your `list` 
    var tree = GetTree(list, 0); 
} 

public List<Tree> GetTree(List<Personal> list, int parent) { 
    return list.Where(x => x.ParentId == parent).Select(x => new Tree { 
     Id = x.Id, 
     Name = x.Name, 
     List = GetTree(list, x.Id) 
    }).ToList(); 
} 
+0

Wenn Sie einen Baum mit generischen Typ erstellen können, bitte teilen Sie Ihre Beispiele. Danken! – LazyCatIT

Antwort

15

Sie Rekursion verwenden sollten ParentID, die mit ihrer eigenen ID übereinstimmt

public void SomeMethod() 
    { 
     // here you get your `list` 
     var tree = GetTree(list, 0); 
    } 

    public List<Tree> GetTree(List<Personal> list, int parent) 
    { 
     return list.Where(x => x.ParentId == parent).Select(x => new Tree 
     { 
      Id = x.Id, 
      Name = x.Name, 
      List = x.ParentId != x.Id ? GetTree(list, x.Id) : new List<Tree>() 
     }).ToList(); 
    } 
+0

Vielen Dank für Ihre Antwort! Aber wenn ich Ihren Code anwende, löst er eine Ausnahme "System.StackOverflowException" aus. Sie können es erneut überprüfen. – LazyCatIT

+2

Es kann passieren, wenn Sie irgendwelche Elemente in "Liste" mit zyklischen Links haben. Zum Beispiel: [{{Id = 1, ParentId = 2}, {Id = 2, ParentId = 1}] (http://en.wikipedia.org/wiki/Cycle_graph) – YD1m

+0

Es wurde eine Anpassung hinzugefügt, um den Fall zu behandeln, in dem jemand hat einen Wurzelknoten mit ParentId = Id –

0

Wie oben nur dieser Code überprüft, für den Fall, dass Ihr Wurzelknoten hat ein:

public List<Tree> GetTree(List<Personal> list) 
     { 
      var listFormat = list.Select(x => new Tree 
       { 
        Id = x.Id, 
        Name = x.Name, 
        ParentId = x.ParentId 
       }).ToList(); 

      var lookup = listFormat.ToLookup(f => f.ParentId); 
      foreach (var tree in listFormat) 
      { 
       tree.List = lookup[tree.Id].ToList(); 
      } 

      return listFormat; 
     } 
+1

Dies würde nur den Fall erkennen, in dem 2 Knoten sich direkt als Eltern beziehen (# 1 -> # 2 -> # 1 -> etc.). Wenn Sie einen dritten Knoten einführen (# 1 -> # 2 -> # 3 -> # 1 -> etc), würde der Zyklus wieder seinen Kopf nach oben ziehen. – BTownTKD

Verwandte Themen