2013-08-27 239 views
1

我有一個包含多列的DataTable。如果某列重複的值,我需要刪除該行並添加數量。例如,下面的數據表從DataTable中刪除具有相同列值的行並添加相應的值

ITEM QTY 
------------ 
1  20 
2  10 
2  10 
3  20 

將成爲:

ITEM QTY 
----------- 
1  20 
2  20 
3  20 

這是我做過什麼

var table = dt.AsEnumerable() 
.GroupBy(row => row.Field("ITEM")) 
.Select(group => group.First()) 
.CopyToDataTable(); 

它消除了額外的行,但不會加起來的數量。所以請在這方面幫助我。

+0

[請在此輸入鏈接的描述]試試這個[1 ] [1]:http://stackoverflow.com/questions/4415519/bestw ay-to-remove-duplicate-entries-from-a-data-table –

回答

7

您可以使用Sum。您只需首先找到重複行:

var dupGroups = dt.AsEnumerable() 
    .GroupBy(row => row.Field<int>("ITEM")) 
    .Where(g => g.Count() > 1); 

現在您可以使用它們來獲取總和並從表格中刪除冗餘行。

foreach (var group in dupGroups) 
{ 
    DataRow first = group.First(); 
    int sum = group.Sum(r => r.Field<int>("QTY")); 
    first.SetField("QTY", sum); 
    foreach (DataRow row in group.Skip(1)) 
     dt.Rows.Remove(row); 
} 

或在一個查詢中創建一個新的DataTable

DataTable newTable = dt.AsEnumerable() 
    .GroupBy(row => row.Field<int>("ITEM")) 
    .Select(g => 
    { 
     DataRow first = g.First(); 
     if (g.Count() > 1) 
     { 
      int sum = g.Sum(r => r.Field<int>("QTY")); 
      first.SetField("QTY", sum); 
     } 
     return first; 
    }) 
    .CopyToDataTable(); 

然而,即使是第二種方法修改,因爲您使用CopyToDatatable創建一個新的DataTable這可能是不希望的原始表。您需要克隆原始表(DataTable newTable = dt.Clone();)以獲取具有相同模式的空表。然後使用NewRow + ItemArray.Clone()table.ImportRow創建實際克隆而不修改原始數據。

參見:C# simple way to copy or clone a DataRow?

編輯:下面是一個例子,你怎麼能不接觸原始表創建一個克隆:

DataTable newTable = dt.Clone(); 
var itemGroups = dt.AsEnumerable() 
    .GroupBy(row => row.Field<int>("ITEM")); 
foreach (var group in itemGroups) 
{ 
    DataRow first = group.First(); 
    if (group.Count() == 1) 
     newTable.ImportRow(first); 
    else 
    { 
     DataRow clone = newTable.Rows.Add((object[])first.ItemArray.Clone()); 
     int qtySum = group.Sum(r => r.Field<int>("QTY")); 
     clone.SetField("QTY", qtySum); 
    } 
} 
+0

感謝您的回答和評論。第二種方法很有幫助。 – Sara

+0

@Sara:但第二種方法是最「危險」的,因爲它以微妙的方式修改了兩個表。如果我不想創建新表和'table.Clone()'+'ImportRow',我會使用第一個,如果我想創建具有總和值的副本表。 –

+0

@Sara:添加了一個示例(未經測試),以顯示如何在不修改原始表的情況下使用累計數據創建克隆。 –

1

這不會更改原始DataTable

var table = dt.Copy().AsEnumerable() 
         .GroupBy(row=>row["ITEM"]) 
         .Select(g=> { 
           DataRow dr = g.First(); 
           dr.SetField("QTY", g.Sum(x=>x.Field<int>("QTY"))); 
           return dr; 
          }) 
         .CopyToDataTable(); 
+0

如果使用'Sum()'而不是'Count()',這會很好。 –

+0

@WillemDuncan謝謝你,錯過了! –

+0

你也不會在任何地方使用'dr' – musefan

3
var table = dt.AsEnumerable() 
    .GroupBy(row => row.Field<int>("ITEM")) 
    .Select(group => { 
     var row = group.First(); 
     row['QTY'] = group.Sum(x => x.Field<int>('QTY')); 
     return row; 
    }).CopyToDataTable(); 
+0

但是,由於OP使用'CopyToDatatable'來創建一個新的'DataTable',所以這會修改原始表,這可能是不受歡迎的。順便說一句,同樣的問題[我的第二種方法](http://stackoverflow.com/a/18463169/284240)。您需要克隆原始表,並使用'NewRow' +'ItemArray.Clone()'或'table.ImportRow'創建一個真正的克隆而不修改原始數據。 –

+0

@TimSchmelter:你說的對,+1點你的點 –

+0

@Cuong Le謝謝。有用。它修改了原文,但這是小問題。 – Sara

相關問題