2016-02-12 2 views
1

Слияние двух похожих таблиц, где у меня есть 2 поля (идентификатор и количество), и в конечном итоге таблица, где у меня может быть несколько записей для одного ID. Я хочу, чтобы результирующая таблица имела только 1 запись для каждого идентификатора, тогда как SUMMING соответствовало количеству для каждого идентификатора. После долгих поисков Google я пришел с этим кодом:C# DataTable: эффективнее Group By и Sum?

DataTable dt1 = new DataTable("Table1"); 
    DataTable dt2 = new DataTable("Table2"); 

    dt1.Columns.Add("ID", typeof(Int32)); 
    dt1.Columns.Add("Quantity", typeof(Int32)); 
    dt1.Rows.Add(new object[] { 1, 1 }); 
    dt1.Rows.Add(new object[] { 2, 2 }); 
    dt1.Rows.Add(new object[] { 3, 3 }); 
    dt1.Rows.Add(new object[] { 4, 4 }); 

    dt2.Columns.Add("ID", typeof(Int32)); 
    dt2.Columns.Add("Quantity", typeof(Int32)); 
    dt2.Rows.Add(new object[] { 1, 100 }); 
    dt2.Rows.Add(new object[] { 3, 100 }); 
    dt2.Rows.Add(new object[] { 4, 100 }); 

    dt1.Merge(dt2); 

    var datas = dt1.AsEnumerable() 
     .GroupBy(r => new { Col1 = r["ID"] }) 
     .Select(g => g.First()["Quantity"] = g.Sum(x => int.Parse(x["Quantity"].ToString()))) 
     .ToList(); 

    dt1 = dt1.AsEnumerable().GroupBy(r => new { Col1 = r["ID"] }) 
     .Select(x => x.First()).CopyToDataTable(); 

Однако, я чувствую, что есть способ сделать это более эффективно, как таблица получает дважды сканируются в этом случае. У кого-нибудь есть предложения?

Еще одна вещь, в качестве бонусного вопроса, я бы хотел найти общее количество по всей результирующей таблице, идеально по-эффективному (это WHILE).

UPDATE: Да, я знаю, DataTable не является мудрой структурой данных, но из-за характера нашего проекта я вынужден работать с ними. Я был бы очень признателен за предложение о том, как использовать здесь промежуточную структуру данных, но в конце мне нужен DataTable.

+0

Ну, это может быть сделано различными способами. Например, вы можете избавиться от подхода linq и отсканировать свою таблицу в одном цикле при суммировании величин в отдельном 'Dictionary ' с идентификаторами в качестве ключей и величин в качестве значений. –

+0

Я бы просто получил данные отсортированы и сделать простой цикл, проходящий через оба в то же время, и суммирование при необходимости. Или, если будет много данных, и сортировка потребует времени, то комментарий Энди хороший. Также позволит легко получить общее количество. Это один из примеров, когда несколько строк кода работают лучше, чем LINQ (хотя кто-то может также придумать версию LINQ). С другой стороны, DataTables довольно плох в производительности, поэтому, если у вас огромный набор данных, они не самые лучшие. –

+0

Почему вы используете данные, они сосут – CRice

ответ

1
//your method 
public void YourMethod() 
{ 
    Dictionary<int, int> result = new Dictionary<int, int>(); 

    int length = 0; 

    if(dt1.Rows.Count > dt2.Rows.Count) 
     length = dt1.Rows.Count 
    else 
     length = dt2.Rows.Count 

    for(int i=0; i < length - 1; i++) 
    { 
     AddRowValue(dt1, result, i); 
     AddRowValue(dt2, result, i); 
    } 

} 


public AddRowValue(DataTable tbl, Dictionary<int, int> dic, int index) 
{ 
    if(index > tbl.Rows.Count) 
     return; 

    DataRow row = tbl.Rows[index]; 

    int idValue = Convert.ToInt32(row["ID"]); 
    int quantityValue = Convert.ToInt32(row["Quantity"]); 

    if(dic.Keys.Contains(idValue) 
     dic[idValue] = dic[idValue] + quantityValue; 
    else 
     dic.Add(idValue, quantityValue); 
} 

Вам нужно что-то подобное, вы можете использовать словарь в конце, результат будет сохранен в словаре.

+0

Загрузка словаря приведет к потере любых преимуществ. Группировка делает то же самое * в конце концов. –

+0

@PanagiotisKanavos Я не уверен, как группа работает под linq, но здесь, по крайней мере, вы используете ее один раз. В своем коде он делает 2 группы. Он может легко проверить, какой подход лучше с секундомером. – mybirthname

+0

@mybirthname, чтобы сделать ответ полным, вам нужно добавить код, который обновляет начальную таблицу, чтобы включить ВСЕ уникальные идентификаторы ONCE и с правильной суммой. – cubrman