比较具有相同结构的多个数据表
本文关键字:数据表 结构 比较 | 更新日期: 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);
}