C# - 从DataTable中删除具有相同列值的行

时间:2013-03-27 16:06:22

标签: c# linq datatable filtering

我有一个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,但我想这将是一个大问题,我必须使用比较器。

6 个答案:

答案 0 :(得分:9)

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

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

答案 1 :(得分:3)

我正在解决同样的情况并发现它非常有趣,并希望分享我的发现。

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

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

    1. 如果根据一个列和列类型的不同是 int ,那么我更希望LINQ查询。
    2.   DataTable newDatatable = dt.AsEnumerable()
                                 .GroupBy(dr => dr.Field<int>("ID"))
                                 .Select(dg => dg).Take(1)
                                 .CopyToDataTable();
      
      1. 如果根据一个列和列类型的不同是字符串,那么我更喜欢循环。
      2. 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);
        }
        

        第三是我最喜欢的。

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

        希望它有所帮助。

答案 2 :(得分:2)

不一定是最有效的方法,但可能最具可读性:

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

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

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

答案 3 :(得分:2)

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

答案 4 :(得分:1)

你可以试试这个

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

答案 5 :(得分:1)

这是实现这一目标的一种方式, 您只需使用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;
}

OutPut:正如您所期待的那样

enter image description here

For moreLinq sample code view my blog