如果我有一个像这样结构的数据表:
emp_num name status session_id
22 john 0 4
22 john 0 5
34 moh 1 3
35 Ran 0 3
35 Ran 0 4
如何将其转换为数据表:
emp_num name status session_id1 session_id2 session_id3 session_id4 session_id5
22 john 0 0 0 0 1 1
34 moh 1 0 0 1 0 0
35 Ran 0 0 0 1 1 0
我尝试使用循环创建自定义数据表,但它不是通用的,我想要一些如此通用的东西,所以如果我添加更多列或会话数量增加我没有超出范围异常..
答案 0 :(得分:2)
using System.Data;
public static class DataTableExtensionMethods
{
public static DataTable TransposeIntegerColumnIntoColumns(this DataTable dt, int indexColumnToEstablishDuplicateRows, int integerColumnIdToTranspose, string transposedColumnName)
{
//Protection if the column to transpose is not an integer or doesn't exist
if (integerColumnIdToTranspose >= dt.Columns.Count) return null;
var columnDataType = dt.Columns[integerColumnIdToTranspose].DataType;
if (columnDataType != typeof(int)) return null;
//Get max sessions number
int maxColumnNumber = 0;
foreach (DataRow dr in dt.Rows)
{
int? number = dr.Field<int?>(integerColumnIdToTranspose);
if (number != null)
{
maxColumnNumber = Math.Max(maxColumnNumber, (int)number);
}
}
//Protection if there are zero rows or the maxColumnNumber is 0
if (dt.Rows.Count == 0 || maxColumnNumber == 0) return null;
//Make a copy of the table so we can remove duplicate rows and add the transposed columns
DataTable result = dt.Copy();
//Add columns to store the session_ids
for (int i = 1; i <= maxColumnNumber; i++)
{
DataColumn dc = new DataColumn(transposedColumnName + i.ToString(), typeof(int));
dc.DefaultValue = 0;
//Possibly make an overloaded method that supports inserting columns
result.Columns.Add(dc);
}
//Remove rows with duplicated employees
for (int i = 0; i < result.Rows.Count; i++)
{
int duplicateRow = GetRowIndexById(result, indexColumnToEstablishDuplicateRows, result.Rows[i][indexColumnToEstablishDuplicateRows].ToString(), i + 1);
if (duplicateRow > -1)
{
result.Rows.RemoveAt(duplicateRow);
}
}
//Populate the transposed columns with values in the integer Column To Transpose
foreach (DataRow dr in dt.Rows)
{
int? sessionNumber = dr.Field<int?>(integerColumnIdToTranspose);
if (sessionNumber == null) continue;
int rowIndex = GetRowIndexById(result, indexColumnToEstablishDuplicateRows, dr[indexColumnToEstablishDuplicateRows].ToString(), 0);
result.Rows[rowIndex][transposedColumnName + sessionNumber.ToString()] = 1; //or +=1 if you want to increment the number
}
//Remove the integerColumnIdToTranspose (again overload this method if you want to keep this column)
result.Columns.RemoveAt(integerColumnIdToTranspose);
return result;
}
//Net 4 implementation with optional parameter
//private static int GetRowIndexById(DataTable dt, int indexColumnToEstablishDuplicateRows, string id, int startLookAtRow = 0)
private static int GetRowIndexById(DataTable dt, int indexColumnToEstablishDuplicateRows, string id, int startLookAtRow)
{
for (int i = startLookAtRow; i < dt.Rows.Count; i++)
{
if (dt.Rows[i][indexColumnToEstablishDuplicateRows].ToString() == id) return i;
}
return -1;
}
}
致电代码:
private void button1_Click(object sender, EventArgs e)
{
DataTable dt = GetData();
DataTable result = dt.TransposeIntegerColumnIntoColumns(0, 3, "session_id");
}
private DataTable GetData()
{
DataTable dt = new DataTable();
dt.Columns.Add("emp_num", typeof(int));
dt.Columns.Add("name");
dt.Columns.Add("status", typeof(int));
dt.Columns.Add("session_id", typeof(int));
DataRow dr = dt.NewRow();
dr["emp_num"] = 22;
dr["name"] = "John";
dr["status"] = 0;
dr["session_id"] = 4;
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["emp_num"] = 22;
dr["name"] = "John";
dr["status"] = 0;
dr["session_id"] = 5;
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["emp_num"] = 34;
dr["name"] = "Moh";
dr["status"] = 1;
//dr["session_id"] = null;
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["emp_num"] = 35;
dr["name"] = "Ran";
dr["status"] = 0;
dr["session_id"] = 3;
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["emp_num"] = 35;
dr["name"] = "Ran";
dr["status"] = 0;
dr["session_id"] = 4;
dt.Rows.Add(dr);
return dt;
}
结果是: