2013-08-27 2 views
1

У меня есть DataTable с несколькими столбцами. Если значение определенного столбца повторяется, мне нужно удалить эту строку и добавить к ней количества. Например, после 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/best-w 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

@ Сара: Но второй подход является самым «опасным», так как он тонко изменяет обе таблицы. Я бы использовал первый, если я не хочу создавать новую таблицу и '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

 Смежные вопросы

  • Нет связанных вопросов^_^