3

我想检查一个 DataTable 中的 DataRow 是否存在于另一个 DataTable 中。

我有两个数据表。将会有一些相同的 DataRows 并且存在于两者中。如果我知道每次都会有哪些列,这将非常容易,但我不知道。使用类似于...的东西

datatable.Rows[i].Field <String> columnName);

将不起作用,因为此字段可能是整数、字符串或日期/时间。但是,我确实知道这两个文件具有相同的列名。

我的代码是零碎的,但这就是它目前的样子。现在我生成一个列名列表,仅此而已。

for (var h = 0; h < origDbfFile.datatable.Columns.Count; h++) {

     columnNames.Add(origDbfFile.datatable.Columns[h].ColumnName);

}

我有一个循环噩梦,如果有人能找到更清洁的解决方案,将不胜感激!

for (int g = 0; g < origDbfFile.dataset.Tables[0].Rows.Count; g++)
{

     for (int h = 0; i < modDbfFile.dataset.Tables[0].Columns.Count; h++)
     {
           foreach (String columnName in columnNames)
           {
           String rowValue = origDbfFile.dataset.Tables[0].Rows[g].Field<String>(Convert.ToString(columnName));
           //test data
           result += "Column name: &nbsp: " + columnName + "<br/>";
           result += "Value &nbsp; " + rowValue + "<br/><br/>";
           //if logic will go below

            }

      }

 }
4

3 回答 3

2

我的解决方案是不以整数、字符串或日期/时间的形式获取值……而是作为通用对象。然后从那里我可以将其转换为字符串,然后将其作为字符串进行比较。

//check each column name for a change
foreach (String columnName in columnNames)
{
    //this grabs whatever value is in that field                            
    String origRowValue = "" + origRow.Field<Object>(columnName);
    String modRowValue = "" + modRow.Field<Object>(columnName);

    //check if they are the same
    if (origRowValue.Equals(modRowValue))
    {
        //if they aren the same, increase the number matched by one
        numberMatched++;
        //add the column to the list of columns that don't match

    }
    else
    {
        mismatchedColumns.Add(columnName);
    }

}

聪明的解决方案还是什么?谢谢各位的帮助 :)

于 2013-05-28T16:53:54.193 回答
2

假设您对行值的装箱/拆箱和值/引用类型没有任何问题,那么您的代码几乎就是您在给定情况下所能做的所有事情。

当然,如果你喜欢它们,你可以使用 linq 和扩展方法让它变得更漂亮

public static class DataRowExtensions
{
    public static int IndexIn(this DataRow thisRow, DataTable table)
    {
        return table.Rows
            .OfType<DataRow>()
            .Select((row, i) => new { row, index = i + 1 })
            .Where(pair => EqCondition(thisRow, pair.row))
            .Select(pair => pair.index)
            .FirstOrDefault() - 1;
    }

    public static bool EqCondition(DataRow row1, DataRow row2)
    {
        // check for the equality of row values
        return true;
    }
}

...

for (int i = 0; i < tab1.Rows.Count; i++)
{
    var index = tab1.Rows[i].IndexIn(tab2);

    if (index < 0)
    {
        Console.WriteLine("The row at index {0} was not found in second table", i);
    }
    else
    {
        Console.WriteLine("The row at index {0} was found in second table at index", i, index);
    }
}

但除了在找到第一个匹配项后中断之外,代码完全相同。

我的建议是使用 ids 相等性,但请记住,大多数情况下数据来自具有索引的数据源,您可能会遇到这种情况。

PS。在你的第二个有2个错误

  • 你声明了 h 但使用 i
  • 我想你应该使用 .
于 2013-05-27T20:56:13.230 回答
0

如果您使用的是 .Net 3.5 或更高版本,则类似这样的内容将为您提供两个表中都存在的列名列表。

var columns = origDbfFile.datatable.Columns
    .Select(o => o.ColumnName)
    .Intersect(modDbfFile.datatable.Columns
               .Select(m => m.ColumnName));

虽然我不确定这是否能解决您的整体问题。你能再澄清一点吗?

于 2013-05-27T19:06:46.250 回答