2016-11-29 105 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; 
}