【问题标题】:Compare two datatables and format results比较两个数据表并格式化结果
【发布时间】:2012-05-13 02:28:43
【问题描述】:

我知道如何在 sql 中执行此操作,但对于 c#..我不知道如何比较两个数据表。

假设:

第一个数据表:

Name  |  Balance | Description
Smith |   1200   | Smith owes 600
Jordan|   4000   | Hi Jordan
Brooks|   5000   | I like my cat
Navaro|   6000   | description here
Gates |   9010   | omg

第二个数据表:

Name  |  Balance | Description
Smith |   1600   | Smith owes 600
Jordan|   4200   | I'M JORDAN
Clay  |   9000   | Test description
Brooks|   5000   | I like my cat

我想将比较结果转储到一个简单的 html 表格中。

Soooo...结果应该是这样的:

基本上我需要的是:

  1. 显示不同的列并显示数据

  2. 如果所有列都相同,则不显示记录

  3. 显示仅存在于第一个数据表中的记录(只是名称)

  4. 显示仅存在于第二个数据表中的记录(只是名称)

在 sql 中,您可以执行合并,然后进行旋转。

但是在 C# 中, 我的发现: 我可以使用 except 或 intersect,但它会返回一个 dattable。 except\intersection 函数是否有任何格式化选项?

我正在寻找有关如何以最佳方式实现这一目标的建议。 (每个数据表中大约有 100 列)。所有都应该按名称进行比较。

【问题讨论】:

    标签: c# asp.net datatable asp.net-4.0


    【解决方案1】:

    这是您需要在 .cs 文件中包含的代码...

    (我只创建了这两个空类以避免在代码中出现Dictionary<object, Dictionary<string, Tuple<object, object>>>,但您可以根据需要替换它)

    protected class Differences : Dictionary<object, RowDifferences>
    {
    }
    
    protected class RowDifferences : Dictionary<string, Tuple<object, object>>
    {
    }
    
    protected Differences GetDifferences(DataTable table1,
                                         DataTable table2,
                                         out IEnumerable<object> onlyIn1,
                                         out IEnumerable<object> onlyIn2)
    {
        var arr1 = new DataRow[table1.Rows.Count];
        var arr2 = new DataRow[table2.Rows.Count];
    
        table1.Rows.CopyTo(arr1, 0);
        table2.Rows.CopyTo(arr2, 0);
    
        onlyIn1 = arr1.Where(x1 => arr2.All(x2 => x1[0] != x2[0])).Select(dr => dr[0]);
        onlyIn2 = arr2.Where(x1 => arr1.All(x2 => x1[0] != x2[0])).Select(dr => dr[0]);
    
        var differences = new Differences();
    
        foreach (var x1 in arr1)
        {
            foreach (var x2 in arr2)
            {
                if (x1[0] == x2[0])
                {
                    var rowDifferences = new RowDifferences();
    
                    for (var i = 1; i < x1.ItemArray.Length; i++)
                    {
                        if (x1.ItemArray[i] != x2.ItemArray[i])
                        {
                            rowDifferences.Add(table1.Columns[i].ColumnName,
                                               new Tuple<object, object>(x1.ItemArray[i], x2.ItemArray[i]));
                        }
                    }
    
                    differences.Add(x1[0], rowDifferences);
                }
            }
        }
    
        return differences;
    }
    
    protected void GenerateTables(out DataTable table1, out DataTable table2)
    {
        table1 = new DataTable();
        table2 = new DataTable();
    
        table1.Columns.Add("Name");
        table1.Columns.Add("Balance");
        table1.Columns.Add("Description");
    
        table2.Columns.Add("Name");
        table2.Columns.Add("Balance");
        table2.Columns.Add("Description");
    
        table1.Rows.Add("Smith", 1200, "Smith owes 600");
        table1.Rows.Add("Jordan", 4000, "Hi Jordan");
        table1.Rows.Add("Brooks", 5000, "I like my cat");
        table1.Rows.Add("Navaro", 6000, "description here");
        table1.Rows.Add("Gates", 9010, "omg");
    
        table2.Rows.Add("Smith", 1600, "Smith owes 600");
        table2.Rows.Add("Jordan", 4200, "I'M JORDAN");
        table2.Rows.Add("Clay", 9000, "Test description");
        table2.Rows.Add("Brooks", 5000, "I like my cat");
    }
    

    下面是一个如何在 .aspx 文件中构建表格的示例:

    <%
        DataTable table1, table2;
        GenerateTables(out table1, out table2);
    
        IEnumerable<object> onlyIn1, onlyIn2;
        var differences = GetDifferences(table1, table2, out onlyIn1, out onlyIn2);
    %>
    
    <table>
        <thead>
            <tr>
                <th>Name</th> 
                <th>RecordName</th> 
                <th>1st Datatable</th> 
                <th>2nd Datatable</th> 
            </tr>
        </thead>
        <tbody>
            <%
                foreach (var difference in differences)
                {
            %>
            <tr>
                <td><%=difference.Key%></td>
            </tr>
            <%
                    foreach (var rowDifferences in difference.Value)
                    {
            %>
            <tr>
                <td></td>
                <td><%=rowDifferences.Key%></td>
                <td><%=rowDifferences.Value.Item1%></td>
                <td><%=rowDifferences.Value.Item2%></td>
            </tr>
            <%
                    }
                }
            %>
            <tr>
                <td>Only 1st datatable</td>
            </tr>
            <%
                foreach (var name in onlyIn1)
                {
            %>
            <tr>
                <td><%=name%></td>
            </tr>
            <%
                }
            %>
            <tr>
                <td>Only 2st datatable</td>
            </tr>
            <%
                foreach (var name in onlyIn2)
                {
            %>
            <tr>
                <td><%=name%></td>
            </tr>
            <%
                }
            %>
        </tbody>
    </table>
    

    从这里开始,按照您的意愿设计表格应该不难了。

    所以你剩下的主要事情是将GenerateTables 更改为一些查询逻辑,甚至将其内联到GetDifferences 中。

    查找算法大概可以完善。目前最坏的情况是 O(m * n * k),m 和 n 分别是 table1 和 table2 中的行数,k 是列数。我已经可以想出很多方法来改进它,但我会把这些留给你。这应该让你开始很好。

    请注意,此算法假定两个表之间的列相等。

    如果对解决方案有任何不清楚的地方,请告诉我,祝你好运!

    【讨论】:

    • 最后我能够实现这个解决方案,而且效果惊人。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多