3

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

4

6 回答 6

10

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

  var result = dt.AsEnumerable()
                 .GroupBy(r => r.Field<int>("ID"))
                 .Select(g => g.First())
                 .CopyToDataTable();
于 2013-03-27T16:11:22.630 回答
3

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

  1. 如果要基于ALL COLUMNS来区分行。
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);
}

第三个是我最喜欢的。

我可能已经回答了一些问题中没有提出的问题。它的意图很好,也没有什么兴奋。

希望能帮助到你。

于 2014-06-24T13:28:41.850 回答
2

你可以试试这个

DataTable uniqueCols = dt.DefaultView.ToTable(true, "ID");
于 2013-03-27T16:10:24.643 回答
2

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

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();
于 2013-03-27T16:12:50.650 回答
2
  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();
于 2013-03-27T16:37:03.923 回答
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;
}

输出:如你所料

在此处输入图像描述

更多Linq示例代码查看我的博客

于 2013-04-10T07:18:54.327 回答