2013-08-13 26 views
5

Tôi có tập dữ liệu chứa 4 cột. Tên, khóa, khóa cha, Cấp. Tôi cần phải chuyển đổi DataTable này thành một cấu trúc cây. Tôi đính kèm một hình ảnh mà sẽ cung cấp cho bạn một số ý tưởng những gì tôi muốn làm. Cách hiệu quả nhất để chuyển đổi DataTable thành một đối tượng mà tôi có thể sử dụng để tạo ra một cấu trúc cây là gì. Hãy giúp tôi.Chuyển đổi kết quả của bảng dữ liệu thành cây bằng C#

Xin lưu ý: Dữ liệu có thể có bất kỳ thứ tự nào trong DataTable. Có thể sắp xếp dataTable trên cột Cấp đầu tiên và sau đó trên cột ParentKey không? Tôi nghĩ, Nếu tôi có thể làm điều đó, sẽ dễ dàng chuyển đổi đầu ra thành cấu trúc cây.

enter image description here

Tôi đã thêm một lớp mà bắt chước các bộ dữ liệu & Tôi đã sắp xếp dữ liệu trong 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; 

      // By default, the 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 = from item in source 
         where 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; 
      } 
     } 
    } 





} 
+0

Cấu trúc cây của cái gì? Một lớp học? –

+0

Bạn không cần "Cấp độ". Key và ParentKey là đủ để xây dựng các cây không giới hạn trong một bảng tự tham khảo. – Robert

+0

@SriramSakthivel: Có. cấu trúc cây của một lớp. – SharpCoder

Trả lời

3

tôi sử dụng phương pháp mở rộng sau đây để làm điều này loại điều:

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>(
     this 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>(
     this 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 = from item in source 
        where 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; 
     } 
    } 

Trong trường hợp của một DataTable như nguồn, bạn có thể sử dụng nó như thế này:

var hierarchy = 
    sourceTable.AsEnumerable() 
       .ToHierarchy(row => row.IsNull("ParentKey"), 
          (parent, child) => parent.Field<int>("Key") == 
               child.Field<int>("ParentKey")) 

(hierarchyIEnumerable<Node<DataRow>>)

Lưu ý rằng nếu bạn def ine quan hệ cha-con trong chính số DataTable, bạn đã có cấu trúc cây ... bạn chỉ cần chọn gốc (các mục không có cha mẹ).

+0

Tôi nhận được lỗi thời gian biên dịch khi sử dụng mã này. Tôi đã cập nhật câu hỏi của tôi với đề xuất của bạn – SharpCoder

+0

@Brown_Dynamite, phương pháp ToHierarchy không phải là thành viên của Node , đó là một phương pháp mở rộng vì vậy nó phải ở trong lớp tĩnh –

+0

thậm chí sau khi thêm các phương thức đó vào lớp tĩnh, tôi gặp lỗi tương tự :( – SharpCoder

Các vấn đề liên quan