C# 合并N个数据表,同时对其中一列求和

C# 合并N个数据表,同时对其中一列求和,c#,linq,datatable,C#,Linq,Datatable,我有N个数据表,我需要将它们合并到一个数据表中,同时对所有表的“value”列求和。下面的例子 请注意:它可以是任意数量的要合并的表,而且字段是动态的,这意味着它不一定只有“年”在那里,它可以是除“值”列之外的任何内容,并且这些表将具有相同的列。我的快速脏解决方案可能会是这样的 public class Program { static void Main() { //make dummy data List<DataTable> d

我有N个数据表,我需要将它们合并到一个数据表中,同时对所有表的“value”列求和。下面的例子


请注意:它可以是任意数量的要合并的表,而且字段是动态的,这意味着它不一定只有“年”在那里,它可以是除“值”列之外的任何内容,并且这些表将具有相同的列。

我的快速脏解决方案可能会是这样的

public class Program
{
    static void Main()
    {
        //make dummy data
        List<DataTable> dts = new List<DataTable>();

        Random rnd = new Random();
        for (int i = 0; i < 20; i++)
        {
            var dt = new DataTable();

            dt.Columns.Add("foo", typeof(int));
            dt.Columns.Add("bar", typeof(int));
            dt.Columns.Add("baz", typeof(int));
            dt.Columns.Add("Value", typeof(int));

            for (int j = 0; j < 1000; j++)
            {
                dt.Rows.Add(rnd.Next(1, 5), rnd.Next(1, 5), rnd.Next(1, 5), rnd.Next(1, 2000));
            }
            dts.Add(dt);
        }

        //dummy data complete

        // the grouping step
        var intermediateResult = dts.SelectMany(x => x.Rows.Cast<DataRow>()).GroupBy(x => x, new NotValueColumnComparer()).Select(x => new { grp = x.Key, sum = x.Sum(y => y.Field<int>("Value")) });


        // transform back into a data tabe
        var result = new DataTable();

        foreach (var col in dts.First().Columns.Cast<DataColumn>())
        {
            result.Columns.Add(col.ColumnName);
        }

        foreach (var item in intermediateResult)
        {
            var row = result.NewRow();

            foreach (var grpField in item.grp.Table.Columns.Cast<DataColumn>().Where(x => x.ColumnName != "Value"))
            {
                row[grpField.ColumnName] = item.grp[grpField.ColumnName];
            }
            row["Value"] = item.sum;

            result.Rows.Add(row);
        }
        //transform end

    }

    //the class that does the trick
    public class NotValueColumnComparer : IEqualityComparer<DataRow>
    {
        //compare all columns but the Value column
        public bool Equals(DataRow x, DataRow y)
        {
            foreach (var col in x.Table.Columns.Cast<DataColumn>())
            {
                if (col.ColumnName != "Value")
                    if (x[col.ColumnName] != y[col.ColumnName])
                        return false;
            }
            return true;
        }


        //as a simple hash code ... just xor the values hash codes
        public int GetHashCode(DataRow obj)
        {
            int res = 0;
            foreach (var col in obj.Table.Columns.Cast<DataColumn>())
            {
                if (col.ColumnName != "Value")
                    res ^= obj[col].GetHashCode();
            }
            return res;
        }
    }
}
公共类程序
{
静态void Main()
{
//制作虚拟数据
列表dts=新列表();
随机rnd=新随机();
对于(int i=0;i<20;i++)
{
var dt=新数据表();
添加(“foo”,typeof(int));
添加(“条”,类型(int));
添加(“baz”,类型(int));
添加(“值”,类型(int));
对于(int j=0;j<1000;j++)
{
添加(rnd.Next(1,5),rnd.Next(1,5),rnd.Next(1,5),rnd.Next(1,5),rnd.Next(1,2000));
}
添加(dt);
}
//虚拟数据完成
//分组步骤
var intermediateResult=dts.SelectMany(x=>x.Rows.Cast()).GroupBy(x=>x,new notvaluecolumncomarer()).Select(x=>new{grp=x.Key,sum=x.sum(y=>y.Field(“Value”));
//转换回数据表
var result=新数据表();
foreach(dts.First().Columns.Cast()中的变量col)
{
result.Columns.Add(col.ColumnName);
}
foreach(中间结果中的var项)
{
var row=result.NewRow();
foreach(item.grp.Table.Columns.Cast()中的var grpField,其中(x=>x.ColumnName!=“Value”))
{
行[grpField.ColumnName]=项.grp[grpField.ColumnName];
}
行[“值”]=item.sum;
结果.行.添加(行);
}
//变换端
}
//做这个把戏的班级
公共类NotValueColumnComparer:IEqualityComparer
{
//比较除值列以外的所有列
公共布尔等于(数据行x、数据行y)
{
foreach(x.Table.Columns.Cast()中的var col)
{
如果(列名称!=“值”)
如果(x[col.ColumnName]!=y[col.ColumnName])
返回false;
}
返回true;
}
//作为一个简单的散列码…只需对散列码的值进行异或运算
public int GetHashCode(DataRow obj)
{
int res=0;
foreach(obj.Table.Columns.Cast()中的变量col)
{
如果(列名称!=“值”)
res^=obj[col].GetHashCode();
}
返回res;
}
}
}
如果你不害怕额外的库,你可能想看看动态LINQ