C# 使用动态列数连接数据表的函数方法
我有一个项目,它允许用户通过左键连接到C# 使用动态列数连接数据表的函数方法,c#,linq,datatable,functional-programming,C#,Linq,Datatable,Functional Programming,我有一个项目,它允许用户通过左键连接到列表(将通过助手方法转换为数据表)向数据表添加列。目前,我有一个正在运行的实现: public static DataTable ListToDataTable<T>(this IList<T> data) { DataTable dt = new DataTable(); PropertyDescriptorCollection props = TypeDescript
列表
(将通过助手方法转换为数据表
)向数据表
添加列。目前,我有一个正在运行的实现:
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;
}
公共静态数据表ListToDataTable(此IList数据)
{
DataTable dt=新的DataTable();
PropertyDescriptorCollection props=TypeDescriptor.GetProperties(typeof(T));
for(int i=0;i
我希望能够传入一个列表
作为最后一个参数,并且在选择新
块中,新匿名类型的列数是可变的。从功能上考虑。
尝试隔离基本情况,并给出可直接转换为所选函数语言的递归定义
让我们看看在伪ML/F#中,join
的定义是什么:
您需要正确地构建match
函数,以比较正确的列,以及传递给map
的函数以构建新行(在我的示例中只是一个元组)
在C#(不太优雅,有一些低效,但希望在填写Match
和Create
后完成)中,通用版本可能如下所示:
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;
}
公共布尔匹配(A、B)
{
//匹配码
返回true;
}
公共C创建(A、B)
{
//创造新记录
返回默认值(C);
}
公共IList连接(IList a、IList b)
{
如果(!a.Any()| |!b.Any())返回新列表();
提前风险值=a[0];
var bMatches=b.其中(bEl=>Match(前面,bEl));
var newCs=bMatches.Select(bEl=>Create(aHead,bEl)).ToList();
newCs.AddRange(Join(a.Skip(1.ToList(),b));//递归调用
返回newCs;
}
我对ML和F完全不熟悉。就目前而言,您能否为该ML提供一些C#伪代码?这在我看来相当深奥。
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;
}