2017-07-24 72 views
1

我有表層次列表如下:不同的輸出小孩和父母的層次列表

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

我要輸出到listTtem如果孩子LVL1加|___然後+值,如果孩子拉特2加<space>然後|___然後+值

輸出:

1 
|___ 3 
|___ 5 
    |___ 4 
|___ 7 
    |___ 2 
      |___ 6 
       |___ 8 
    |___ 11 
9 
|___ 10 

什我完成了:

public class MyClass 
{ 
    public List<MyClass> Children = new List<MyClass>(); 
    public string ID { get; set; } 
    public string ParentID { get; set; } 
    public string Name { get; set; } 
} 

// GET: Reporting 
public ActionResult Index() 
{ 
    List<MyClass> ofitems = new List<MyClass>(); 
    var dbs = db.ORG_FUNCTION.Select(pk => new { pk.FUNCTION_ID, pk.FUNCTION_PARENT_ID, pk.NAME }); 
    foreach (var s in dbs) 
    { 
     ofitems.Add(new MyClass { ID = s.FUNCTION_ID.ToString(), ParentID = s.FUNCTION_PARENT_ID.ToString(), Name = s.NAME }); 
    } 
    Action<MyClass> SetChildren = null; 
    SetChildren = parent => 
    { 
     parent.Children = ofitems 
      .Where(childItem => childItem.ParentID == parent.ID) 
      .ToList(); 
     //Recursively call the SetChildren method for each child. 
     parent.Children 
      .ForEach(SetChildren); 
    }; 
    //ViewBag.list = ????; 
    return View(); 
} 

但它只是顯示相同的輸出。如何獲得父親孩子的不同輸出

+0

不是答案,而是建議:你的'SetChildren'是二次('O(N * N)') ,而它可以是線性的('O(n)')。 –

回答

1

您需要遞歸地遍歷樹狀結構以正確輸出。
你的算法確實使用遞歸,但它只是填充Children屬性,它可以線性甚至做到:

var byNodeId = ofitems.ToDictionary(x => x.ID, x => x); 
foreach (var node in ofitems) 
{ 
    // add current node to its parent's Children 
    byNodeId[node.ParentID].Children.Add(node); 
} 

是很重要,因爲你的算法需要O(n*n)操作,以填補Children這是不如它可以n倍。

即使在填寫Children之後,仍然需要通過樹來DFS (Depth-First Search) - 可以使用Queue或遞歸完成。
那怎麼遞歸的方式可能看起來像:

public static class TreeFormatter 
{ 
    private static string FormatTreeItem(MyClass item, int depth) 
    { 
     if (depth == 0) 
      return $"{item.ID}"; // you can use Name in return 

     return $"{new string(' ', (depth - 1) * 8)}|___ {item.ID}"; // 8 spaces per level  
    } 

    private static void FormatSubtree(StringBuilder sb, List<MyClass> items, string current, int depth) 
    { 
     foreach (var child in items.Where(x => x.ParentID == current)) // perhaps .OrderBy? 
     { 
      sb.AppendLine(FormatTreeItem(child, depth)); 
      FormatSubtree(sb, items, child.ID, depth + 1); 
     } 
    } 

    public static string Format(List<MyClass> items) 
    { 
     var sb = new StringBuilder(); 
     FormatSubtree(sb, items, "0", 0); // "0" = root 
     return sb.ToString(); 
    } 
} 

結果:

LINQPad demo

而且你的控制器可以是這樣的:

public ActionResult Index() 
{ 
    List<MyClass> ofitems = _repository.GetMyClasses(); // contains db access logic 

    // This actually can be in repository too: 
    var byNodeId = ofitems.ToDictionary(x => x.ID, x => x); 
    foreach (var node in ofitems) 
    { 
     // add current node to its parent's Children 
     byNodeId[node.ParentID].Children.Add(node); 
    } 

    ViewBag.ListText = TreeFormatter.Format(ofitems); 
    return View(); 
} 

有這個代碼很多地方在那裏你可以改進它,它只是顯示了這個想法。

+0

hemm ..我會試試@YeldarKurmangaliyev – Stfvns

0

構建MyClass樹很容易。如果你開始這個數據

ILookup<int, int> lookup = source.ToLookup(x => x.ParentID, x => x.ID); 
Func<int, List<MyClass>> build = null; 
build = pid => 
    lookup[pid] 
     .Select(id => new MyClass() 
     { 
      Children = build(id), 
      ID = id, 
      ParentID = pid 
     }) 
     .ToList(); 

List<MyClass> ofitems = build(0); 

var source = new[] 
{ 
    new { ID = 1, ParentID = 0 }, 
    new { ID = 2, ParentID = 7 }, 
    new { ID = 3, ParentID = 1 }, 
    new { ID = 4, ParentID = 5 }, 
    new { ID = 5, ParentID = 1 }, 
    new { ID = 6, ParentID = 2 }, 
    new { ID = 7, ParentID = 1 }, 
    new { ID = 8, ParentID = 6 }, 
    new { ID = 9, ParentID = 0 }, 
    new { ID = 10, ParentID = 9 }, 
}; 

然後你得到這樣的結果:

result

我沒有改變你的MyClass定義

試試這個使用int作爲ID類型而不是字符串,但它也適用於字符串。

輸出也相當簡單。

試試這個:與output(ofitems, 0)

string divider = "|___"; 
Func<IEnumerable<MyClass>, int, IEnumerable<string>> output = null; 
output = (items, n) => 
    items 
     .SelectMany(item => 
      new [] 
      { 
       "".PadLeft(
        divider.Length * (n - 1 > 0 ? n - 1 : 0)) 
        + (n > 0 ? divider : "") 
        + item.ID 
      }.Concat(output(item.Children, n + 1))); 

然後我得到這個:

 
1 
|___3 
|___5 
    |___4 
|___7 
    |___2 
     |___6 
      |___8 
9 
|___10