2014-05-08 181 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