Reputation: 499
I have the following table as example
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
I am looking to get the relation parent/child so I define the following class:
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 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)));
}
}
public void GetChild(Node node, Dictionary<int, Node> map, Dictionary<int, Node> mapf)
{
foreach (var child in node.Children)
{
foreach (var pairf in map)
{
if (child.Id == pairf.Value.ParentId)
{
child.Operator = pairf.Value.Operator;
var parent = map[pairf.Value.ParentId.Value];
child.Children.Add(pairf.Value);
mapf[child.Id] = map[pairf.Value.Id];
//rootNodes.Add(pairf.Value);
}
}
GetChild(child,map,mapf);
}
}
I have successfully got the rootnodes using this code
var map = new Dictionary(); var rootNodes = new List();
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
};
}
var mapf = new Dictionary<int, Node>();
// get rootnods
foreach (var pair in map)
{
if (pair.Value.ParentId.Equals(null))
{
mapf[pair.Value.Id] = map[pair.Value.Id];
rootNodes.Add(pair.Value);
}
}
// get operator for rootnods
foreach (var pair in mapf)
{
foreach (var pairf in map)
{
if (pair.Value.Id == pairf.Value.ParentId)
{
pair.Value.Operator = pairf.Value.Operator;
var parent = map[pairf.Value.ParentId.Value];
rootNodes.Add(pairf.Value);
GetChild(rootNodes., map, mapf);
}
}
}
I need to build node tree first. Then start at the root nodes copying the operator from the children. Progress to the children and copy their children's operator. For example
[92 Node: / 92 (, 36),(, 37)]
[93 Node: + 93 (, 38),(, 39),(, 40)]
[94 Node: / 94 (, 69),(, 70)]
[95 Node: + 95 (, 81),(, 82)]
[96 Node: + 96 (, 83),(, 84),(, 85),(, 86),(, 87),(, 88),(, 89)]
The code above doesn't return this result . How can I modify it ?
Upvotes: 0
Views: 1916
Reputation: 6975
Starting from scratch:
public IEnumerable<Node> CreateTree(DataTable table)
{
var nodes = GetNodes(table).ToList();
var roots = new List<Node>();
foreach(var node in nodes)
{
if(node.ParentId==null)
roots.Add(node);
else
{
var parent = nodes.Single(n => n.Id == node.ParentId);
CreateRelationship(parent, node);
}
}
foreach (var root in roots)
{
UpdateOperators(root);
}
return nodes;
}
private void CreateRelationship(Node parent, Node child)
{
child.Parent = parent;
parent.Children.Add(child);
}
private IEnumerable<Node> GetNodes(DataTable table)
{
return from DataRow row in table.Rows select CreateNode(row);
}
private Node CreateNode(DataRow row)
{
return new Node
{
Id = Convert.ToInt32(row["PNLId"]),
ParentId = row.IsNull("PNLParentId") ? default(int?) : Convert.ToInt32(row["PNLParentId"]),
Operator = Convert.ToString(row["Operator"]),
Sign = Convert.ToString(row["Sign"])
};
}
private void UpdateOperators(Node parent)
{
if (!parent.Children.Any())
return;
parent.Operator = parent.Children.First().Operator;
foreach (var child in parent.Children)
{
UpdateOperators(child);
}
}
Node
should keep everything from your code except the GetChild
method. Also, Children
should be declared as an IList<Node>
, not an IList
.
CreateTree
is your point of entry- it returns an IEnumerable
of all nodes, with all parent/child relationships throughout the tree correct.
Upvotes: 1