2014-03-13 20 views
0

我有一個項目,允許用戶通過左加入到List<T>(它將通過輔助方法轉換爲DataTable)將列添加到DataTable。現在我有這個實現其工作:使用動態列數聯接數據表的功能方法

public static DataTable ListToDataTable<T>(this IList<T> data) 
     { 
      DataTable dt = new DataTable(); 
      PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(T)); 
      for (int i = 0; i < props.Count; i++) 
      { 
       PropertyDescriptor prop = props[i]; 
       dt.Columns.Add(prop.Name, prop.PropertyType); 
      } 
      object[] values = new object[props.Count]; 
      foreach (T t in data) 
      { 
       for (int i = 0; i < values.Length; i++) 
       { 
        values[i] = props[i].GetValue(t); 
       } 
       dt.Rows.Add(values); 
      } 
      return dt; 
     } 
     //for purposes of this demo, the first column in leftTable is always the 
     //column that's joined on 
     public static DataTable JoinWithList<T>(this DataTable leftTable, IList<T> data,string propertyToAdd) 
     { 
      var rightTable = new DataTable(); 
      rightTable = data.ListToDataTable(); 
      var joiningColumn = leftTable.Columns[0].ColumnName; 
      var columnIndex = 0; 
      //find the index of type T whose property is the same as leftTable's 

      PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(T)); 
      for (int i = 0; i < props.Count; i++) 
      { 
       PropertyDescriptor prop = props[i]; 
       if (prop.Name ==joiningColumn) 
       { 
        columnIndex = i; 
       } 
      } 
      var results = (from u in leftTable.AsEnumerable() 
          join s in rightTable.AsEnumerable() 
          on u[0] equals s[columnIndex] into ps 
          from p in ps.DefaultIfEmpty() 
          select new 
          { 
           MembershipId = u[0], 
           UserName = u[1], 
           //some sort of function to iterate over and add columns here 
           Salary = p == null ? 0.01 : p[propertyToAdd] = p[propertyToAdd] 
          }).ToList().ListToDataTable(); 

      return results; 
     } 

我希望能夠在List<string>傳遞的最後一個參數和select new塊內有一個可變數目appeneded新的匿名類型的列。

回答

1

從功能上考慮。 嘗試隔離基本情況並給出遞歸定義,這些定義可以直接翻譯成您選擇的功能性語言。

讓我們看到join的定義是僞-ML/F#是什麼:

_ join [] = [] 
[] join _ = [] 
H::T join L = 
    append 
     (L |> choose (match H) |> map (e -> (H, e))) 
     (T join L) 

您需要正確地構建match功能,比較合適的列,並傳遞給map功能建設新行(在我的例子中只是一個元組)。

在C#(那麼優雅,有一些效率低下,但希望一旦完成並MatchCreate填寫)的通用版本可能看起來像:

public bool Match<A, B>(A a, B b) 
    { 
     // Match code 
     return true; 
    } 

    public C Create<A, B, C>(A a, B b) 
    { 
     // Create new record 
     return default(C); 
    } 

    public IList<C> Join<A, B, C>(IList<A> a, IList<B> b) 
    { 
     if(!a.Any() || !b.Any()) return new List<C>(); 
     var aHead = a[0]; 
     var bMatches = b.Where(bEl => Match(aHead, bEl)); 
     var newCs = bMatches.Select(bEl => Create<A, B, C>(aHead, bEl)).ToList(); 
     newCs.AddRange(Join<A, B, C>(a.Skip(1).ToList(), b)); // Recursive call 
     return newCs; 
    } 
+0

我與ML和F#完全陌生的。目前,你能否給這個ML提供一些C#僞代碼?這對我來說看起來很體面。 – wootscootinboogie

+0

@wootscootinboogie,編輯添加:-) – Mau

相關問題