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

ios - UICollectionView Self Sizing Cells with Auto Layout -

node.js - ldapjs - write after end error -

DOM Manipulation in Wordpress (and elsewhere) using php -