2013-08-27 240 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

相关问题