2016-11-29 103 views
1

如何数据表列转换为IEnumerable的[]这是需要在R.NET转换数据表的列类型的IEnumerable []

创建一个数据帧我有以下代码:

DataTable dt = CreateDateTable(); 
REngine e = REngine.GetInstance();      
IEnumerable[] columns = new IEnumerable[dt.Columns.Count];     
string[] columnNames = dt.Columns.Cast<DataColumn>() 
         .Select(x => x.ColumnName) 
         .ToArray(); 

for(int i=0; i<dt.Columns.Count; i++) 
    //This is the place where I am stuck. How to convert column to base type array instead of object array 
    columns[i] = dt.Rows.Cast<DataRow>().Select(row => row[i]).ToArray(); 

DataFrame df = e.CreateDataFrame(columns: columns, 
columnNames: columnNames, 
stringsAsFactors: false); 

我出现以下情况例外:

Test 'XXX.ReadResultsTest' failed: System.NotSupportedException : Cannot convert type System.Object[] to an R vector 
     w RDotNet.REngineExtension.ToVector(REngine engine, IEnumerable values) 
     w System.Array.ConvertAll[TInput,TOutput](TInput[] array, Converter`2 converter) 
     w RDotNet.REngineExtension.CreateDataFrame(REngine engine, IEnumerable[] columns, String[] columnNames, String[] rowNames, Boolean checkRows, Boolean checkNames, Boolean stringsAsFactors) 

DataTable拥有不同类型的列,我不知道是什么类型的,所以我不能做到像上面例子double

for (int i = 0; i < dt.Columns.Count; i++) 
     columns[i] = dt.Rows.Cast<DataRow>().Select(row => row.Field<double>(i)).ToArray(); 

UPDATE

到目前为止,我有一个丑陋的解决方案,能不能做到更好?

for (int i = 0; i < dt.Columns.Count; i++) 
{ 
    switch (Type.GetTypeCode(dt.Columns[i].DataType)) 
    { 
     case TypeCode.String: 
      columns[i] = dt.Rows.Cast<DataRow>().Select(row => row.Field<string>(i)).ToArray(); 
      break; 

     case TypeCode.Double: 
      columns[i] = dt.Rows.Cast<DataRow>().Select(row => row.Field<double>(i)).ToArray(); 
      break; 

     case TypeCode.Int32: 
      columns[i] = dt.Rows.Cast<DataRow>().Select(row => row.Field<int>(i)).ToArray(); 
      break; 

     case TypeCode.Int64: 
      columns[i] = dt.Rows.Cast<DataRow>().Select(row => row.Field<long>(i)).ToArray(); 
      break; 

     default: 
      //columns[i] = dt.Rows.Cast<DataRow>().Select(row => row[i]).ToArray(); 
      throw new InvalidOperationException(String.Format("Type {0} is not supported", dt.Columns[i].DataType.Name)); 
    }     
} 

回答

0

下面是如何得到DataTable对象到一个列表(其实现IEnumerable),其表示使用动态型和扩展方法中的表的列结构的对象的:

class Program 
{ 
    static void Main() 
    { 
     var dt = new DataTable(); 
     //populate dt... 

     List<dynamic> dataTableList= dt.DataTableToList(); 
    } 
} 

public static class DataTableExtensions 
{ 
    public static List<dynamic> DataTableToList(this DataTable dt) 
    { 
     var list= new List<dynamic>(); 
     foreach (DataRow row in dt.Rows) 
     { 
      dynamic d = new ExpandoObject(); 
      list.Add(d); 
      foreach (DataColumn column in dt.Columns) 
      { 
       var dic = (IDictionary<string, object>)d; 
       dic[column.ColumnName] = row[column]; 
      } 
     } 

     return list; 
    } 
} 
+1

感谢您的回答,但此解决方案仅适用于数据表结构已知的情况。我需要一个通用的解决方案,而不需要知道数据表的结构。 –

+0

好吧我现在明白了 - 我编辑了我的答案,以说明如何实现这一点。 –

+0

请注意,动态类型列表ia不是相同的广告IEnumerable [],例如数组的数组。这是RDotNet所需的 –

1
public DataFrame DataTableToDataFrame(string name, DataTable dt) 
{ 
    DataFrame dataFrame = null; 

    IEnumerable[] columns = new IEnumerable[dt.Columns.Count]; 
    string[] columnNames = dt.Columns.Cast<DataColumn>() 
          .Select(x => x.ColumnName) 
          .ToArray(); 

    for (int i = 0; i < dt.Columns.Count; i++) 
    { 
     switch (Type.GetTypeCode(dt.Columns[i].DataType)) 
     { 
      case TypeCode.String: 
       columns[i] = dt.Rows.Cast<DataRow>().Select(row => row.Field<string>(i)).ToArray(); 
       break; 

      case TypeCode.Double: 
       columns[i] = dt.Rows.Cast<DataRow>().Select(row => row.Field<double>(i)).ToArray(); 
       break; 

      case TypeCode.Int32: 
       columns[i] = dt.Rows.Cast<DataRow>().Select(row => row.Field<int>(i)).ToArray(); 
       break; 

      case TypeCode.Int64: 
      case TypeCode.Decimal: 
       IEnumerable array = dt.Rows.Cast<DataRow>().Select(row => row.Field<object>(i)).ToArray(); 

       //columns[i] = dt.Rows.Cast<DataRow>().Select(row => row.Field<long>(i)).ToArray(); 
       //columns[i] = dt.Rows.Cast<DataRow>().Select(row => row.Field<decimal>(i)).ToArray(); 

       columns[i] = ListToIenumerable(array); 
       break; 

      default: 
       columns[i] = dt.Rows.Cast<DataRow>().Select(row => row[i]).ToArray(); 
       //throw new InvalidOperationException(String.Format("Type {0} is not supported", dt.Columns[i].DataType.Name)); 
       break; 
     } 
    } 

    dataFrame = REngine.CreateDataFrame(columns: columns, columnNames: columnNames, stringsAsFactors: false); 
    REngine.SetSymbol(name, dataFrame); 

    return dataFrame; 
} 

这是?

+0

欢迎来到SO。请给你的答案提供一些背景或解释。仅限代码不符合质量标准。请参阅http://stackoverflow.com/help/how-to-answer –

0
public IEnumerable<int> ListToIenumerable(IEnumerable enumerable) 
{ 
    List<int> list = new List<int>(); 

    foreach (object obj in enumerable) 
    { 
     list.Add(Convert.ToInt32(obj.ToString())); 
    } 

    IEnumerable<int> returnValue = list.ToArray(); 

    return returnValue; 
}