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.

enter image description here

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

Popular posts from this blog

Issues changing the value of an element in an array in matlab -

php - MySQLi binding parameters in a prepared statement doesn't work unless inserted after "WHERE" -

vb.net - Alternative to the T-SQL AS keyword -