datatable - Converting result of data table into tree using C# -
i have dataset contains 4 columns. name, key, parentkey, level. need convert datatable tree structure. attaching image give idea want do. efficient way convert datatable object can use generate tree structure. please help.
please note: data can come in order in datatable. possible sort datatable on first level column , on parentkey column? think, if can that, easy convert output tree structure.
i have added class mimic dataset & have sorted data within datatable.
namespace sortdatatable { public class program { private static void main(string[] args) { datatable table = new datatable(); table.columns.add("name", typeof (string)); table.columns.add("key", typeof (string)); table.columns.add("parentkey", typeof (string)); table.columns.add("level", typeof (int)); table.rows.add("a", "a1", null, 1); table.rows.add("b", "a2", "a1", 2); table.rows.add("c", "a3", "a1", 2); table.rows.add("d", "a4", "a1", 2); table.rows.add("e", "a5", "a2", 3); table.rows.add("f", "a6", "a5", 4); table.rows.add("g", "a7", "a3", 3); table.rows.add("h", "a8", "a4", 3); table.rows.add("i", "a9", "a4", 3); table.rows.add("j", "a10", "a4", 3); table.rows.add("k", "a11", "a10", 4); table.rows.add("l", "a12", "a10", 4); table.rows.add("m", "a13", "a12", 5); table.rows.add("n", "a14", "a12", 5); table.rows.add("o", "a15", "a10", 4); dataview view = table.defaultview; // default, first column sorted ascending. view.sort = "level, parentkey desc"; foreach (datarowview row in view) { console.writeline(" {0} \t {1} \t {2} \t {3}", row["name"], row["key"], row["parentkey"], row["level"]); } console.readkey(); } } public class node<t> { internal node() { } public t item { get; internal set; } public int level { get; internal set; } public node<t> parent { get; internal set; } public ilist<node<t>> children { get; internal set; } public static ienumerable<node<t>> tohierarchy<t>( ienumerable<t> source, func<t, bool> startwith, func<t, t, bool> connectby) { if (source == null) throw new argumentnullexception("source"); if (startwith == null) throw new argumentnullexception("startwith"); if (connectby == null) throw new argumentnullexception("connectby"); return source.tohierarchy(startwith, connectby, null); } private static ienumerable<node<t>> tohierarchy<t>(ienumerable<t> source, func<t, bool> startwith, func<t, t, bool> connectby, node<t> parent) { int level = (parent == null ? 0 : parent.level + 1); var roots = item in source startwith(item) select item; foreach (t value in roots) { var children = new list<node<t>>(); var newnode = new node<t> { level = level, parent = parent, item = value, children = children.asreadonly() }; t tmpvalue = value; children.addrange(source.tohierarchy(possiblesub => connectby(tmpvalue, possiblesub), connectby, newnode)); yield return newnode; } } } }
i use following extension method kind of thing:
public class node<t> { internal node() { } public t item { get; internal set; } public int level { get; internal set; } public node<t> parent { get; internal set; } public ilist<node<t>> children { get; internal set; } } public static ienumerable<node<t>> tohierarchy<t>( ienumerable<t> source, func<t, bool> startwith, func<t, t, bool> connectby) { if (source == null) throw new argumentnullexception("source"); if (startwith == null) throw new argumentnullexception("startwith"); if (connectby == null) throw new argumentnullexception("connectby"); return source.tohierarchy(startwith, connectby, null); } private static ienumerable<node<t>> tohierarchy<t>( ienumerable<t> source, func<t, bool> startwith, func<t, t, bool> connectby, node<t> parent) { int level = (parent == null ? 0 : parent.level + 1); var roots = item in source startwith(item) select item; foreach (t value in roots) { var children = new list<node<t>>(); var newnode = new node<t> { level = level, parent = parent, item = value, children = children.asreadonly() }; t tmpvalue = value; children.addrange(source.tohierarchy(possiblesub => connectby(tmpvalue, possiblesub), connectby, newnode)); yield return newnode; } }
in case of datatable
source, can use this:
var hierarchy = sourcetable.asenumerable() .tohierarchy(row => row.isnull("parentkey"), (parent, child) => parent.field<int>("key") == child.field<int>("parentkey"))
(hierarchy
ienumerable<node<datarow>>
)
note if define parent-child relation in datatable
itself, already have tree structure... need select roots (items no parent).
Comments
Post a Comment