![](/img/trans.png)
[英]c# How to merge two data rows & columns into one in datatable by using ItemArray?
[英]How to merge rows in a DataTable when data in multiple columns match?
我試圖找出一種在column1,column2,column3,column4匹配時合並DataTable中的行的好方法。 有沒有人有關於如何在VB.NET和/或C#中實現這一點的指針或想法?
DataTable with duplicate rows to merge
-------------------------------------------------------------
| Column1 | Column2 | Column3 | Column4 | Column5 | Column6 |
-------------------------------------------------------------
| 123456 | 6 | 54 | 5 | 0.00 | 36.78 |
| 123456 | 6 | 54 | 5 | 21.00 | 0.00 |
| 123456 | 6 | 54 | 8 | 0.00 | 102.09 |
| 123456 | 6 | 54 | 8 | 6.50 | 0.00 |
Final DataTable with merged rows
-------------------------------------------------------------
| Column1 | Column2 | Column3 | Column4 | Column5 | Column6 |
-------------------------------------------------------------
| 123456 | 6 | 54 | 5 | 21.00 | 36.78 |
| 123456 | 6 | 54 | 8 | 6.50 | 102.09 |
這是一個非LINQ替代方案。 它的作用是迭代第一個表中的每一行。 然后,它檢查輔助表以查看其中是否有符合條件的行。 如果有,則在其他列中添加值。 如果沒有,則將整行添加到新表中。
// Clone() only clones the table structure. It does not also clone the data.
DataTable dtFinal = dtOriginal.Clone();
for (int i = 0; i < dtOriginal.Rows.Count; i++)
{
bool isDupe = false;
for (int j = 0; j < dtFinal.Rows.Count; j++)
{
if (dtOriginal.Rows[i][0].ToString() == dtFinal.Rows[j][0].ToString()
&& dtOriginal.Rows[i][1].ToString() == dtFinal.Rows[j][1].ToString()
&& dtOriginal.Rows[i][2].ToString() == dtFinal.Rows[j][2].ToString())
{
dtFinal.Rows[j][3] = int.Parse(dtFinal.Rows[j][3].ToString()) + int.Parse(dtOriginal.Rows[i][3].ToString());
isDupe = true;
break;
}
}
if (!isDupe)
{
dtFinal.ImportRow(dtOriginal.Rows[i]);
}
}
您可以對此進行擴展,以在匹配條件和添加邏輯中包含更多/更少的列。 您可能還會想到一些東西來擺脫列號硬編碼,例如將它們迭代到特定索引或其他東西。 這一切都取決於您的要求。 這應該會給你一個不錯的起點。
使用linq嘗試此代碼:
DataTable dataTable1 = new DataTable();
dataTable1.Columns.Add(new DataColumn("Column1", typeof(int)));
dataTable1.Columns.Add(new DataColumn("Column2", typeof(int)));
dataTable1.Columns.Add(new DataColumn("Column3", typeof(int)));
dataTable1.Columns.Add(new DataColumn("Column4", typeof(int)));
dataTable1.Columns.Add(new DataColumn("Column5", typeof(decimal)));
dataTable1.Columns.Add(new DataColumn("Column6", typeof(decimal)));
dataTable1.Rows.Add(123456, 6, 54, 5, 0, 36.78);
dataTable1.Rows.Add(123456, 6, 54, 5, 21, 0);
dataTable1.Rows.Add(123456, 6, 54, 8, 0, 102.09);
dataTable1.Rows.Add(123456, 6, 54, 8, 6.50, 0);
//Select the rows where columns 1-4 have repeated same values
var distinctRows = dataTable1.AsEnumerable()
.Select(s => new
{
unique1 = s.Field<int>("Column1"),
unique2 = s.Field<int>("Column2"),
unique3 = s.Field<int>("Column3"),
unique4 = s.Field<int>("Column4"),
})
.Distinct();
//Create a new datatable for the result
DataTable resultDataTable = dataTable1.Clone();
//Temporary variables
DataRow newDataRow;
IEnumerable<DataRow> results;
decimal tempCol5;
decimal tempCol6;
//Go through each distinct rows to gather column5 and column6 values
foreach (var item in distinctRows)
{
//create a new row for the result datatable
newDataRow = resultDataTable.NewRow();
//select all rows in original datatable with this distinct values
results = dataTable1.Select().Where(
p => p.Field<int>("Column1") == item.unique1
&& p.Field<int>("Column2") == item.unique2
&& p.Field<int>("Column3") == item.unique3
&& p.Field<int>("Column4") == item.unique4);
//Preserve column1 - 4 values
newDataRow["Column1"] = item.unique1;
newDataRow["Column2"] = item.unique2;
newDataRow["Column3"] = item.unique3;
newDataRow["Column4"] = item.unique4;
//store here the sumns of column 5 and 6
tempCol5 = 0;
tempCol6 = 0;
foreach (DataRow dr in results)
{
tempCol5 += (decimal)dr["Column5"];
tempCol6 += (decimal)dr["Column6"];
}
//save those sumns in the new row
newDataRow["Column5"] = tempCol5;
newDataRow["Column6"] = tempCol6;
//add the row to the result dataTable
resultDataTable.Rows.Add(newDataRow);
}
我建議看一下使用DataTableExtensions,它允許你使用LINQ連接2個數據表來填充最終的數據表。
我需要等到今晚才能發布任何示例代碼,但我覺得在此之前你將能夠找出所需的LINQ語法。
http://msdn.microsoft.com/en-us/library/system.data.datatableextensions(v=vs.110).aspx
您可以使用LINQ-To-DataTable
,尤其是Enumerable.GroupBy
。 您必須使用匿名類型進行分組,並使用循環來創建具有唯一值的新表。
我使用Enumerable.Sum
來獲取最后兩列的總和:
Dim first4ColGroups = From row In table
Let first4colums = New With {
Key .col1 = row.Field(Of Int32)(0),
Key .col2 = row.Field(Of Int32)(1),
Key .col3 = row.Field(Of Int32)(2),
Key .col4 = row.Field(Of Int32)(3)
}
Group row By first4colums Into RowGroup = Group
Dim tblUnique = table.Clone() ' creates an empty table with the same columns '
For Each grp In first4ColGroups
Dim row As DataRow = tblUnique.Rows.Add()
row.SetField(0, grp.first4colums.col1)
row.SetField(1, grp.first4colums.col2)
row.SetField(2, grp.first4colums.col3)
row.SetField(3, grp.first4colums.col4)
row.SetField(4, grp.RowGroup.Sum(Function(r) r.Field(Of Decimal)(4)))
row.SetField(5, grp.RowGroup.Sum(Function(r) r.Field(Of Decimal)(5)))
Next
我不知道你想要合並的目的,但是,這可能會有效。
List<object> list = new List<object>();
System.Data.DataTable DT2 = new System.Data.DataTable();
private void button1_Click(object sender, EventArgs e)
{
foreach (DataRow row in DT2.Rows)
{
for (int i = 0; i < DT2.Rows.Count; i++)
{
var Tjek = DT2.Rows[i][0];
if (list.Contains(DT2.Rows[i][0]))
{
}
else
{
list.Add(Tjek);
}
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.