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

本文关键字:数据表 结构 比较 | 更新日期: 2023-09-27 17:59:00

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

数据表1:
KeyColumn,ValueColumn
KeyA,ValueA
键B,值B
KeyC,ValueC

数据表2:
KeyColumn,ValueColumn
键B,值B
KeyC,ValueC
KeyD,ValueD

结果应该是这样的:

结果数据表:KeyColumn、ValueColumn(属于DT1)、ValueColumn(属于DT2)
KeyA,ValueA
KeyB,ValueB(DT1的),ValueBKeyC、ValueC(DT1的)、ValueCKeyD nbsp nbsp nbsp nbsp nbsp ValueD

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

我尝试了很多方法,但最终都没有解决方案。有什么想法可以解决这个问题吗?

编辑:
Dictionaries的解决方案太复杂了,所以我继续尝试用Datatables来解决它。问题的根源是出乎意料的。试图将列名重命名为包含一个简单点('.')的,结果将丢失该列中的所有数据
例如,如果您有Datatable dt:
PrimaryColumn,ValueColumn
KeyA1 KeyB1
KeyA2 键B2


dt.Columns[ValueColumn].ColumnName="Value.Column"之后
您将丢失该列中的任何数据。我会问MS,这是不是需要的,或者这是.NET Framework中的一个Bug。

这是我的最后一个代码(C#)。我有列表<字符串>将保留在resultTable中的键。并且List<字符串>将为每个应进行比较的表添加的值。

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

欢迎任何改进!

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

好的,这里是我使用字典版本的一个例子。

Fiddle: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);
    }