c# - 在对其中一列求和时合并 N 个数据表

标签 c# linq datatable

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

enter image description here

请注意:它可以是任何数量的要合并的表,而且字段是动态的,这意味着它不是必需的,只有“年”在那里,它可以是任何东西,但“值”列将始终存在,并且表格将具有相同的列。

最佳答案

我的快速解决方案可能看起来像这样......

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;
        }
    }
}

如果你不怕额外的库,你可能想看看 ad dynamic LINQ ...

关于c# - 在对其中一列求和时合并 N 个数据表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43252495/

相关文章:

c# - 动态移动表格单元格(向上/向下)-javascript

c# - 将一天中的时间转换为 .net 中的 fr-CA - 错误的短时间格式字符串?

c# - 禁用或使其只读成为文本框 (.net) 中值的一部分

c# - P/Invoke - 将委托(delegate)编码为函数指针 + void*

c# - 为什么我不能分配 LINQ Find() 或 FirstOrDefault() 结果的返回值?

c# - 如何使用 LINQ 从数据库设置自动完成功能?

c# - 使用 dapper 的通用参数化 sql 查询

c# - 如何从谓词对象中删除重复项?

c# - DataTable.Load() 时应用程序中断,问题在哪里?

php - 根据第一个表的id查询多个表