0

SQLでこれを行う方法は知っていますが、c#の場合..2つのデータテーブルを比較する方法がわかりません。

まあ言ってみれば:

1 番目のデータテーブル:

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

2番目のデータテーブル:

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. 2 番目のデータテーブルにのみ存在するレコードを表示 (名前のみ)

SQLでは、マージしてからピボットすることができます。

しかし、C# では、私の調査結果: except または intersect を使用できますが、1 つの dattable が返されます。except\intersection 関数の書式設定オプションはありますか?

これを最善の方法で達成する方法についてのアドバイスを探しています。(各データテーブルには約 100 列あります)。すべてを名前で比較する必要があります。

4

1 に答える 1

3

.cs ファイルに含める必要があるコードは次のとおりです...

(私はこれらの 2 つの空のクラスを作成して、コードに含まれないようにしまし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 は列数です。私はすでにそれを大幅に改善する方法を考えていますが、それらはあなたに任せます。これで、うまく始められるはずです。

このアルゴリズムは、2 つのテーブルの列が等しいと想定していることに注意してください。

解決策について不明な点があればお知らせください。頑張ってください!

于 2012-05-13T04:25:36.597 に答える