2013-07-11 2 views
7

У меня есть список структур данных:Как построить иерархию с использованием Linq для объекта?

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

, и я хочу, чтобы построить дерево:

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

Как построить дерево с Linq объекта? Я должен использовать, но это не работает точно, смотрите ниже:

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

Если вы можете построить дерево с использованием универсального типа, поделитесь своими примерами. Спасибо! – LazyCatIT

ответ

15

Вы должны использовать рекурсию:

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

Спасибо за ваш ответ! Но когда я применяю ваш код, он вызывает исключение «System.StackOverflowException». Вы можете проверить это снова. – LazyCatIT

+2

Это может произойти, если у вас есть элементы в 'list' с циклическими ссылками. Например: [{{Id = 1, ParentId = 2}, {Id = 2, ParentId = 1}] (http://en.wikipedia.org/wiki/Cycle_graph) – YD1m

+0

Добавлена ​​настройка ниже, чтобы обрабатывать случай, когда у кого-то есть корневой узел с ParentId = Id –

0

То же, что и выше только для данного кода проверки для случая, что корневой узел имеет ParentID, соответствующий его собственному идентификатору.

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(); 
    } 
+1

Это будет определять только случай, когда два узла напрямую ссылаются друг на друга как на родителей (# 1 -> # 2 -> # 1 -> и т. д.). Если вы введете 3-й узел (# 1 -> # 2 -> # 3 -> # 1 -> и т. Д.), Цикл снова запустит его голову. – BTownTKD

Смежные вопросы