比较几个具有相同结构的数据表

时间:2014-04-17 21:02:22

标签: c# .net datatable

我正在从.csv文件创建数据表。这部分实际上有效。我目前的问题是以下问题: 我必须比较两个或更多具有相同结构的Datatable。所以

Datatable1:
KeyColumn,ValueColumn
KeyA,ValueA
KeyB,ValueB
KeyC,ValueC

Datatable2:
KeyColumn,ValueColumn
KeyB,ValueB
KeyC,ValueC
KeyD,ValueD

这最终应该是这样的:

ResultDatatable: KeyColumn,ValueColumn(DT1),ValueColumn(DT2)
KeyA,ValueA
KeyB,ValueB(DT1),ValueB(DT2)
KeyC,ValueC(DT1),ValueC(DT2)
KeyD,ValueD

由于不同的ColumnNames,我甚至无法插入第一个Datatable的数据。另一个问题是,Datatables拥有相同的ColumnNames,因此我无法将它们添加到ResultDatatable中。

我尝试了很多方法,最终没有解决方案。有任何想法如何解决这个问题?

编辑:
使用词典的解决方案太复杂了,所以我继续尝试使用Datatables来解决它。问题的根源是非常意外的。 尝试将列名重命名为,其中包含一个简单的点('。')会导致该列中的丢失所有数据
例如如果你有Datatable dt:
PrimaryColumn,ValueColumn
KeyA1,KeyB1
KeyA2,KeyB2

在zht.Columns [ValueColumn] .ColumnName =“Value.Column”之后;您将丢失该列中的任何数据。如果需要,我会问MS,或者它是否是.NET-Framework中的Bug。

这是我的最终密码(C#)。我有List< string>键,它们将保留在resultTable中。和List< string>值将为每个应该比较的表添加。

private DataTable CompareTables(List<AnalyseFile> files, Query query, List<string> keys, List<string> values) {
            // Add first table completely to resultTable
            DataTable resultTable =
                files[0].GetDataTable(false, query.Header, query.Startstring, query.Endstring, query.Key).Copy();
            foreach (string value in values) {
                resultTable.Columns[value].ColumnName = "(" + files[0].getFileNameWithoutExtension() + ") " + value;
            }

            // Set primary keys
            resultTable.PrimaryKey = keys.Select(key => resultTable.Columns[key]).ToArray();

            // process remaining tables
            for (int i = 1; i < files.Count; i++) {
                DataTable currentTable = files[i].GetDataTable(false, query.Header, query.Startstring, query.Endstring, query.Key);
                // Add value-columns to the resultTable
                foreach (string value in values) {
                    resultTable.Columns.Add("(" + files[i].getFileNameWithoutExtension() + ") " + value);
                }

                // Set again primary keys
                currentTable.PrimaryKey = keys.Select(key => currentTable.Columns[key]).ToArray();

                // populate common Rows 
                foreach (DataRow dataRow in resultTable.Rows) {
                    foreach (DataRow row in currentTable.Rows) {
                        foreach (string key in keys) {
                            if (dataRow[key].ToString().Equals(row[key].ToString())) {
                                foreach (string value in values) {
                                    string colname = "(" + files[i].getFileNameWithoutExtension() + ") " + value;
                                    dataRow[colname] = row[value];
                                }
                            }
                        }
                    }
                }

                // Get all Rows, which do not exist in resultTable yet
                IEnumerable<string> isNotinDT =
                    currentTable.AsEnumerable()
                        .Select(row => row.Field<string>(keys[0]))
                        .Except(resultTable.AsEnumerable().Select(row => row.Field<string>(keys[0])));

                // Add all the non existing rows to resulTable
                foreach (string row in isNotinDT) {
                    DataRow currentRow = currentTable.Rows.Find(row);
                    DataRow dRow = resultTable.NewRow();
                    foreach (string key in keys) {
                        dRow[key] = currentRow[key];
                    }
                    foreach (string value in values) {
                        dRow["(" + files[i].getFileNameWithoutExtension() + ") " + value] = currentRow[value];
                    }
                    resultTable.Rows.Add(dRow);
                }
            }    

            return resultTable;
        }

欢迎任何改进!

1 个答案:

答案 0 :(得分:0)

Ok以下是使用词典的我的版本示例。

小提琴:http://dotnetfiddle.net/AljK9J

    //Setup Sample Data
    var data1 = new Dictionary<string, string>();
    data1.Add("KeyA", "ValueA");
    data1.Add("KeyB", "ValueB");
    data1.Add("KeyC", "ValueC");

    var data2 = new Dictionary<string, string>();
    data2.Add("KeyB", "ValueB");
    data2.Add("KeyC", "ValueC");
    data2.Add("KeyD", "ValueD");


    //Second DataType in the Dictionary could be something other than a Tuple
    var result = new Dictionary<string, Tuple<string, string>>();

    //Fill in for items existing only in data1 and in both data1 and data2
    foreach(var item in data1)
    {
        result.Add(item.Key, new Tuple<string, string>(item.Value, data2.FirstOrDefault(x => x.Key == item.Key).Value));
    }

    //Fill in remaining items that exist only in data2
    foreach(var item in data2.Where(d2 => !result.Any(x => x.Key == d2.Key )))
    {
        result.Add(item.Key, new Tuple<string, string>(null, item.Value));
    }

    //Demonstrating how to access the data
    var formattedOutput = result.Select(x => string.Format("{0}, {1} (of D1), {2} (of D2)", x.Key, x.Value.Item1 ?? "NoValue", x.Value.Item2 ?? "NoValue"));

    foreach(var line in formattedOutput)
    {
        Console.WriteLine(line);
    }