从表构建树

时间:2014-05-08 07:53:21

标签: c#

我定义了以下类Node以获得父/子

的关系
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 个答案:

答案 0 :(得分: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
  • 删除.Value

运行它之后,rootNodes集合将包含1个元素(Id = 1的元素),并且map数组将包含对其父元素的正确对象引用。

<强>解释

pair变量属于foreach循环,包含map的元素。 变量map是一个Node个对象的数组,它是一个在其中声明属性Parent的类 - 它也是Node类型。

Node类型的变量都是对象类型,而不是值类型,因此它们不拥有.Value属性。 但是,您声明的ParentId是可以为空的值类型,因为声明int? - 以及所有可空值类型(请注意?后缀)拥有.Value属性: 因此,对于ParentId,您可以使用ParentId.Value(和.HasValue来检查null)来获取值,但不能使用Parent来获取值,NodeNode个对象。 {{1}}对象的属性需要通过其属性名称直接访问。