c#数据表:更有效的分组方式和总和?

c#数据表:更有效的分组方式和总和?,c#,datatable,group-by,sum,C#,Datatable,Group By,Sum,我合并了两个类似的表,其中我有两个字段(ID和数量),并最终得到一个表,在该表中,我可以为同一ID拥有多条记录。我希望生成的表中每个ID只有一条记录,同时对每个ID的相应数量求和。经过长时间的谷歌搜索,我得出以下代码: DataTable dt1 = new DataTable("Table1"); DataTable dt2 = new DataTable("Table2"); dt1.Columns.Add("ID", typeof(Int32)); dt1

我合并了两个类似的表,其中我有两个字段(ID和数量),并最终得到一个表,在该表中,我可以为同一ID拥有多条记录。我希望生成的表中每个ID只有一条记录,同时对每个ID的相应数量求和。经过长时间的谷歌搜索,我得出以下代码:

    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();
但是,我觉得有一种方法可以更有效地执行此操作,因为在这种情况下,表会被扫描两次。有人有什么建议吗

还有一件事,作为一个额外的问题,我希望以一种理想的有效方式(即分组时)找到整个结果表中的总量

更新:是的,我知道,DataTable不是一个明智的数据结构,但由于我们项目的性质,我不得不与他们合作。如果能给我一个关于如何在这里使用中间数据结构的建议,我将不胜感激,但最后我需要一个DataTable。

//您的方法
//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; if(dt1.Rows.Count>dt2.Rows.Count) 长度=dt1.Rows.Count 其他的 长度=dt2.Rows.Count 对于(int i=0;i待处理行数) 返回; DataRow row=tbl.Rows[索引]; int idValue=Convert.ToInt32(行[“ID”]); int quantityValue=Convert.ToInt32(行[“数量”]); if(dic.Keys.Contains)(idValue) dic[idValue]=dic[idValue]+量化值; 其他的 dic.Add(idValue,quantityValue); }

你需要这样的东西,你可以在最后使用dictionary,结果将存储在dictionary中。

好吧,可以通过多种方式来完成。例如,你可以摆脱linq方法,在单个循环中扫描表,同时在单独的
dictionary
中求和数量,将ID作为键,数量作为值。我会只需对数据进行排序,并进行一个简单的循环,同时对两者进行排序,如果需要求和。或者,如果有很多数据,排序需要时间,那么Andy的评论很好。也可以轻松地获得总数。这是一个示例,其中几行代码比LINQ更好另一方面,DataTables的性能非常差,所以如果你有一个巨大的数据集,它们就不是最好的。为什么你要使用DataTables呢suck@SamiKuhmonen那么,您建议使用什么数据结构呢?我收到的DataTable-s是一个SQL请求的结果(这是我们项目的性质)但对于最后一步,我需要合并它们。我们认为将原始SQL请求变大是不明智的,因此我需要首先将数据表转换为其他结构。那么您有什么建议吗?我还希望有一个指向字典方法的代码示例的链接。数据表在内存中。它们应该非常快与磁盘IO和网络IO相比,你真的在这里得到了什么好处吗?加载字典会扼杀任何性能优势。分组毕竟是做同样的事情的。@PanagiotisKanavos我不确定group by在linq下是如何工作的,但在这里至少你使用了一次。在他的代码中,他使用了2个group by。他可以很容易地检查哪种方法使用秒表更好。@mybirthname若要完成答案,您需要添加代码,以一次更新初始表,使其包含所有唯一ID,并且数量总和正确。不再需要使用datatable,他可以使用dictionary。我没有发现遗漏任何内容,请不要思考,如果不想忽略答案,请尝试。我们正在用一个循环扫描两个表。