【问题标题】:Compare two datatables and delete duplicates (without join)比较两个数据表并删除重复项(无连接)
【发布时间】:2019-01-14 07:33:36
【问题描述】:

我需要比较两个数据表,删除重复的,然后填充一个gridview。

这是我迄今为止尝试过的

DataTable cols = new DataTable();
DataTable cols2 = new DataTable();
DataTable cols3 = cols.Copy();

foreach(DataRow row1 in cols2.Rows) 
{
 bool isRecordExist = false;
 foreach(DataRow row2 in cols.Rows) 
 {
  if (row1 == row2) 
  {
   isRecordExist = true;
  }

  if (!isRecordExist) 
  {
   cols3.ImportRow(row1);
  }
 }
}

dgvfcolumns.DataSource = cols3;

但它只是将第二个数据表(cols2)中的行添加到第一个(cols)中,而不是删除重复项。

有什么想法吗? 我还想问我是否必须将我的数据表转换为数组? 谢谢

编辑 我用这样的组合填充我的第一个数据表...... Obtaining combinations of k elements from n in C#

第二个数据表有一个表中的值,我用一个选择填充它

SqlDataAdapter sqlDa = new SqlDataAdapter("select concat(N1, ' ', N2, ' ',N3, ' ',N4, ' ',N5) FROM Cols2", sqlCon);

【问题讨论】:

  • 您正在比较两个 DataRow 对象,而不是两个 DataRow 对象中的 值。
  • row1 == row2 正在检查 row1 和 row2 是否引用同一个对象。但我怀疑您想检查两个 DataRow 实例中包含的值是否相同:您需要自己检查列。
  • 更确切地说是“查找两个表的交集”部分var contacts = contacts1.AsEnumerable().Intersect(contacts2.AsEnumerable(), DataRowComparer.Default);
  • @xdtTransform 我已经尝试过了,但它不起作用...可能是因为我的数据顺序不同...谢谢

标签: c# linq duplicates


【解决方案1】:

这是一个自定义 [MCVE]。表 1 和表 2 都有唯一行和重复行。

DataTable dataFromSourceA = new DataTable();    
DataTable dataFromSrouceB = new DataTable();

dataFromSourceA.Columns.Add("DataFromSourceA", typeof(string));
dataFromSrouceB.Columns.Add("DataFromSrouceB", typeof(string));

dataFromSourceA.Rows.Add("1,2,3,4,5"); // Dupe                
dataFromSourceA.Rows.Add("2,2");
dataFromSourceA.Rows.Add("4,5,6,7,8");

dataFromSourceB.Rows.Add("1,2,3,4,5"); // Dupe
dataFromSourceB.Rows.Add("2,2,2");
dataFromSourceB.Rows.Add("42");

在使用.AsEnumerable() 之后,您可以简单地使用 LinQ 来查询那些 Datable。
T1 中的行与 T2 中的任何行匹配。

// List of Duplicate
var dupes =
   dataTable1
       .AsEnumerable()
       .Where(r1 =>
            dataTable2
               .AsEnumerable()
               .Any(r2 =>
                   {
                       var c1 = r1.Field<string>(0);
                       var c2 = r2.Field<string>(0);

                       var splitC1 = c1.Split(',').Select(x => x.Trim()).ToList();
                       var splitC2 = c2.Split(',').Select(x => x.Trim()).ToList();

                       return true
                              && (splitC1.Count() == splitC2.Count())
                              && !splitC1.Except(splitC2).Any();
                   }
                )
        );

【讨论】:

  • 感谢您的回复...结果是 0。不幸的是,我只有一列,没有 Id 可比较..
  • 对不起,你是对的在一个 dtbl 我的列的值为 1,2,3,4,5 其他行可能是 2, 3 4, 5, 6,第二个我有 2,4, 5,3,1 我需要比较它们并找到重复项...
  • dataTable1 和 dataTable2 没有相同的顺序。没关系,因为我通过那里的名称访问列。但是如果我们必须使用索引访问它们,代码将是相同的。
  • 对不起,可能不够清楚...数据为 1,2,3,4,5 它们在一行中...
  • 例如Field&lt;string&gt;(3)将给出第4列
【解决方案2】:

您可以使用默认的 DataRowComparer,结合使用 except 和 Union 函数:

    // create the 2 datatables - must have the same schema
    DataTable  dataTable1 = new DataTable();
    dataTable1.Columns.Add(new DataColumn("Id"));
    dataTable1.Columns.Add(new DataColumn("FirstName"));
    dataTable1.Columns.Add(new DataColumn("LastName"));

    DataTable  dataTable2 = dataTable1.Clone(); 

    dataTable1.Rows.Add(new object[] {1, "John", "Doe"}); 
    dataTable1.Rows.Add(new object[] {2, "Peter", "Rabbit"});

    dataTable2.Rows.Add(new object[] {1, "John", "Doe"});
    dataTable2.Rows.Add(new object[] {2, "Peter", "Smith"});

    DataTable resultsTable = dataTable1.Clone();  // table to keep results

    // this will copy all distinct rows into the resultsTable 
    dataTable1.AsEnumerable()
            .Union(dataTable2.AsEnumerable().Except(dataTable1.AsEnumerable(), DataRowComparer.Default))   // all rows in table2 that do not exists in table1
        .ToList()   
        .ForEach(r => resultsTable.ImportRow(r));  // import the distinct rows into the resultsTable.

    DataTable resultsTable2 = dataTable1.Clone();
    // this will copy only the rows that DO NOT exist in both tables into the resultsTable2 (effectively deletes duplicate rows from both tables)
    dataTable1.AsEnumerable().Except(dataTable2.AsEnumerable(), DataRowComparer.Default)
            .Union(dataTable2.AsEnumerable().Except(dataTable1.AsEnumerable(), DataRowComparer.Default))   // all rows in table2 that do not exists in table1
        .ToList()   
        .ForEach(r => resultsTable2.ImportRow(r));  // import the distinct rows into the resultsTable.

【讨论】:

  • @touinta - 我可能没有正确理解你。我之前的答案只提取了在另一个表中没有对应项的行 - 只提取了仅存在于 2 个表中的 1 个表中的行。我更新了我的答案以提取不同行的完整列表。
猜你喜欢
  • 2013-02-02
  • 1970-01-01
  • 2011-04-05
  • 2014-12-16
  • 2020-10-16
  • 2017-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多