【问题标题】:C# - Remove rows with the same column value from a DataTableC# - 从 DataTable 中删除具有相同列值的行
【发布时间】:2013-03-17 19:30:10
【问题描述】:

我有一个DataTable,看起来像这样:

 ID   Name    DateBirth
.......................
 1     aa      1.1.11
 2     bb      2.3.11
 2     cc      1.2.12
 3     cd      2.3.12

这是删除具有相同 ID 的行的最快方法,得到这样的结果(保留第一个出现,删除下一​​个出现):

 ID   Name    DateBirth
.......................
 1     aa      1.1.11
 2     bb      2.3.11
 3     cd      2.3.12

我不想重复传递表格行,因为行号很大。 如果可能,我想使用一些 LinQ,但我想这将是一个很大的查询,我必须使用比较器。

【问题讨论】:

  • 你试过什么?只是ID的问题吗?其他字段不相关?
  • 常用方式。 2 for's 并验证每一行的 ID 字段。如果是重复的,删除它。但这是基本的和低性能的。是的,其他领域无关紧要。只有 ID 很重要。

标签: c# linq datatable filtering


【解决方案1】:

您可以使用 LINQ to DataTable,根据列 ID 进行区分,您可以在此列上分组,然后先进行 选择:

  var result = dt.AsEnumerable()
                 .GroupBy(r => r.Field<int>("ID"))
                 .Select(g => g.First())
                 .CopyToDataTable();

【讨论】:

    【解决方案2】:

    我正在解决同样的情况,发现它很有趣,并想分享我的发现。

    1. 如果要根据所有列区分行。
    DataTable newDatatable = dt.DefaultView.ToTable(true, "ID", "Name", "DateBirth");
    

    您在此处提到的列,只有那些会在newDatatable 中返回。

    1. 如果基于一列的不同且列类型为 int,那么我更喜欢 LINQ 查询。
      DataTable newDatatable = dt.AsEnumerable()
                               .GroupBy(dr => dr.Field<int>("ID"))
                               .Select(dg => dg).Take(1)
                               .CopyToDataTable();
    
    1. 如果基于一列的不同且列类型是字符串,那么我更喜欢循环。
    List<string> toExclude = new List<string>();
    for (int i = 0; i < dt.Rows.Count; i++)
    {
        var idValue = (string)dt.Rows[i]["ID"];
        if (toExclude.Contains(idValue))
        {
            dt.Rows.Remove(dt.Rows[i]);
            i--;
        }
        toExclude.Add(glAccount);
    }
    

    第三个是我最喜欢的。

    我可能已经回答了一些问题中没有提出的问题。这样做是出于好意,也没有什么兴奋。

    希望对你有帮助。

    【讨论】:

    • 如果distinct 基于两列怎么办?不是一个(即,id 在上述情况下)。
    【解决方案3】:

    你可以试试这个

    DataTable uniqueCols = dt.DefaultView.ToTable(true, "ID");
    

    【讨论】:

      【解决方案4】:

      不一定是最有效的方法,但也许是最易读的:

      table = table.AsEnumerable()
          .GroupBy(row => row.Field<int>("ID"))
          .Select(rowGroup => rowGroup.First())
          .CopyToDataTable();
      

      Linq 也更强大。例如,如果您想更改逻辑并且不选择每个 id-group 的第一(任意)行,而是根据DateBirth选择最后一行:

      table = table.AsEnumerable()
          .GroupBy(row => row.Field<int>("ID"))
          .Select(rowGroup => rowGroup
                                .OrderByDescending(r => r.Field<DateTime>("DateBirth"))
                                .First())
          .CopyToDataTable();
      

      【讨论】:

        【解决方案5】:
        1. 获取每个ID 的记录数
        var rowsToDelete = 
            (from row in dataTable.AsEnumerable()
            group row by row.ID into g
            where g.Count() > 1
        
        1. 确定要保留的记录(不知道您的标准;我将按 DoB 排序,然后按Name 并保留第一条记录)并选择其余的
        select g.OrderBy( dr => dr.Field<DateTime>( "DateBirth" ) ).ThenBy( dr => dr.Field<string>( "Name" ) ).Skip(1))
        
        1. 展平
        .SelectMany( g => g );
        
        1. 删除行
        rowsToDelete.ForEach( dr => dr.Delete() );
        
        1. 接受更改
        dataTable.AcceptChanges();
        

        【讨论】:

          【解决方案6】:

          这是实现这一目标的一种方法, 所有你需要使用moreLinq库使用它的功能DistinctBy

          代码:

          protected void Page_Load(object sender, EventArgs e)
          {
            var DistinctByIdColumn = getDT2().AsEnumerable()
                                             .DistinctBy(
                                             row => new { Id = row["Id"] });
            DataTable dtDistinctByIdColumn = DistinctByIdColumn.CopyToDataTable();
          }
          
          
          public DataTable getDT2()
          {
             DataTable dt = new DataTable();
             dt.Columns.Add("Id", typeof(string));
             dt.Columns.Add("Name", typeof(string));
             dt.Columns.Add("Dob", typeof(string));
             dt.Rows.Add("1", "aa","1.1.11");
             dt.Rows.Add("2", "bb","2.3.11");
             dt.Rows.Add("2", "cc","1.2.12");
             dt.Rows.Add("3", "cd","2.3.12");
             return dt;
          }
          

          输出:如您所愿

          For moreLinq sample code view my blog

          【讨论】:

            猜你喜欢
            • 2013-08-30
            • 1970-01-01
            • 2017-11-07
            • 2014-12-15
            • 1970-01-01
            • 1970-01-01
            • 2022-12-17
            • 1970-01-01
            • 2012-01-13
            相关资源
            最近更新 更多