2014-05-08 219 views
1

我爲了定義下面的類節點,以獲得相關的父/子構建樹從表

class Node 
{ 
     public int Id { get; set; } 
     public int? ParentId { get; set; } 
     public string Operator { get; set; } 
     public string Sign { get; set; } 
     public Node Parent { get; set; } 
     public IList<Node> Children { get; set; } 

     public Node() 
     { 
      Children = new List<Node>(); 
     } 

     public override string ToString() 
     { 
      //return "Node: " + Operator + " " + Id + " " + string.Join(",", Children.Select(x => x.Id)); 
      return "Node: " + Operator + " " + Id + " " 
      + string.Join(",", Children.Select(x => string.Format("({0}, {1})", x.Sign, x.Id))); 
     } 
} 

我有以下表爲例

PNLId PNLCode PNLParentId Operator Sign 
0  
49 C 51 + NULL 
50 Z 51 + NULL 
51 Y 107/ NULL 
52 B 107/ NULL 
53 B 108 + NULL 

我在寫了下面的腳本主:

var map = new Dictionary<int, Node>(); 
var rootNodes = new List<Node>(); 

foreach (DataRow row in dt.Rows) 
{ 
    int id = Convert.ToInt32(row["PNLId"]); 
    int? parentId = null; 
    if (!row.IsNull("PNLParentId")) 
    { 
     parentId = Convert.ToInt32(row["PNLParentId"]); 
    } 
    string op = Convert.ToString(row["Operator"]); 
    string sign = Convert.ToString(row["Sign"]); 
    map[id] = new Node 
    { 
     Id = id, 
     ParentId = parentId, 
     Operator = op, 
     Sign=sign 

    }; 
} 

foreach (var pair in map) 
{ 
    if (pair.Value.ParentId.HasValue) 
    { 
     var parent = map[pair.Value.ParentId.Value]; 
     pair.Value.Parent = parent; 
     parent.Children.Add(pair.Value); 
     parent.Operator = pair.Value.Operator; 
    } 
    else 
    { 
     rootNodes.Add(pair.Value); 

    } 
} 

在這種情況下它會返回,對於PNLParentId 107

[107 Node: + 107 (, 51),(, 52)] 

這是不對的,應該是

[107 Node:/107 (, 51),(, 52)] 

如何修改上面的代碼首先建立節點樹。然後從複製操作員的根節點開始。讓孩子進步並複製孩子的操作員?

回答

1

我修復了您編寫的代碼來構建樹。 下面是一些測試數據一起工作(我沒有你的數據庫表):

var map = new Node[] { 
    new Node() { Id=0, ParentId=0, Operator="", Sign=null} 
    ,new Node() { Id=1, ParentId=null, Operator="+", Sign=null} 
    ,new Node() { Id=2, ParentId=3, Operator="+", Sign=null} 
    ,new Node() { Id=3, ParentId=4, Operator="/", Sign=null} 
    ,new Node() { Id=4, ParentId=4, Operator="/", Sign=null} 
    ,new Node() { Id=5, ParentId=1, Operator="+", Sign=null} 
}; 

,這裏是固定的代碼:

// remove Value 
var rootNodes = new List<Node>(); 
foreach (var pair in map) 
{ 
    if (pair.ParentId.HasValue) 
    { 
     var parent = map[pair.ParentId.Value]; 
     pair.Parent = parent; 
     parent.Children.Add(pair); 
     parent.Operator = pair.Operator; 
    } 
    else 
    { 
     rootNodes.Add(pair);  
    } 
} 

的變化是:

  • 添加rootNodes
  • 刪除。值

運行後,rootNodes集合將包含1個元素(Id = 1的元素),並且映射數組將包含正確的對其父元素的引用。

說明:

pair變量屬於foreach循環和包含map元件。 變量mapNode對象的數組,它是您聲明屬性Parent的類 - 它也是類型Node

Node類型的變量都是對象類型,而不是值類型,因此它們不擁有.Value屬性。 但ParentId,你都宣稱,是一個空值類型,因爲聲明int?的 - 和所有可空值類型(注意?後綴)有.Value屬性: 所以對於ParentId,即可獲得價值使用ParentId.Value(和.HasValue檢查爲空),但不適用於Parent,這是一個Node對象。 Node對象的屬性需要通過屬性名直接訪問。

+0

爲什麼要刪除.Value?我沒有明白。 – user3548593

+0

@ user3548593:我編輯了user3615347的答案並添加了一個解釋。希望有所幫助。 – Matt

+0

@ user3548593:你可以在[LinqPad](http://www.linqpad.net/)(這是一個免費的工具)中測試這個答案中的代碼 - 只要把它放到'main()'方法中, rootNodes.Dump(); map.Dump();'最後,然後從你的問題中添加'Node'類。如果運行該示例,則會看到正在輸出窗口中構建的遞歸結構:LinqPad提供的'.Dump()'方法的好處之一! – Matt