如何从数据表中提取所有唯一/不同的行并将这些行保存在具有相同列的新数据表中?
How can I extract all Unique / Distinct Rows from a Datatable and save these rows in a new Datatable with same Columns?
问题
我有一个包含多个列和行的数据表。这些列名称之一是“登录”。此 DataTable 中的某些行具有相同的列“登录”。例如,“登录”为 test123
的 2 行。我需要一个新的 DataTable 只包含这 2 行中的一个(哪一个无关紧要)。
问题
如何从旧数据表创建新数据表,过滤掉“登录”列中具有重复条目的行。新的 DataTable 应该与旧的具有相同的结构/列。实际上,在应用过滤器并找到一些匹配项后,只有 Rows.Count
发生变化。
到目前为止我尝试了什么
Dim distinctDT As DataTable = myDT.DefaultView.ToTable(True, "logon")
--> 只给我一个只有一列的数据表(“登录”)。虽然过滤了唯一值,但它只包含一个列 --> 如果我传入一个包含我所有列名称的数组,它不再过滤唯一值。
Dim names = From row In myDataTable.AsEnumerable() Select row.Field(Of String)("Name") Distinct
--> 给我一个具有唯一值的字符串数组 --> 我需要一个与以前具有相同列的 DataTable
几个选项允许根据特定列的值过滤 DataTable 的 DataRow,以生成具有结果 DataRow 的新 DataTable。
考虑 - 既然你提到了 - selected 哪个 DataRow 并不重要,即任何 duplicate DataRow 都可以:
(如果 select 的 DataRow 在某些时候变得重要,您还可以 OrderBy()
使用另一个列的值进行分组,然后从中选择第一个或最后一个 DataRow有序 collection)
按列的值对数据行进行分组:
- 使用列的值对源 DataTable 的数据行进行分组
- Select 每个分组的第一个 DataRow
- 调用
CopyToDataTable()
方法生成新的DataTable
导致:
Dim newDt = [DataTable].AsEnumerable().
GroupBy(Function(r) r("[Column Name]")).
Select(Function(g) g.First()).
CopyToDataTable()
使用自定义 EqualityComparer:
- 构建一个简单的 EqualityComparer class 来比较两个数据行的同一列的值 objects
- 使用
Distinct()
方法并传递自定义 EqualityComparer,使用用作比较器的列的名称进行初始化
- 调用
CopyToDataTable()
方法
此方法的优点是可重用(即,您无需重建查询,只需使用要比较的列的名称初始化比较器即可)
导致:
Dim newDt = [DataTable].AsEnumerable().
Distinct(New DataRowColumnComparer("[Column Name]")).
CopyToDataTable()
自定义 EqualityComparer
:
这是一种基本的比较器。您当然可以扩展它以使用不同的索引器(表示列索引的整数或 DataColumn 引用)。
Public Class DataRowColumnComparer
Implements IEqualityComparer(Of DataRow)
Private ReadOnly t As String = String.Empty
Public Sub New(key As String)
If String.IsNullOrEmpty(key) Then Throw New ArgumentException("Empty key")
t = key
End Sub
Public Overloads Function Equals(dr1 As DataRow, dr2 As DataRow) As Boolean Implements IEqualityComparer(Of DataRow).Equals
If dr1 Is Nothing AndAlso dr2 Is Nothing Then Return True
If dr1 Is Nothing OrElse dr2 Is Nothing Then Return False
Return dr1(t).Equals(dr2(t))
End Function
Public Overloads Function GetHashCode(dr As DataRow) As Integer Implements IEqualityComparer(Of DataRow).GetHashCode
If dr(t) Is Nothing OrElse dr(t) Is DBNull.Value Then Return 0
Return dr(t).GetHashCode()
End Function
End Class
问题
我有一个包含多个列和行的数据表。这些列名称之一是“登录”。此 DataTable 中的某些行具有相同的列“登录”。例如,“登录”为 test123
的 2 行。我需要一个新的 DataTable 只包含这 2 行中的一个(哪一个无关紧要)。
问题
如何从旧数据表创建新数据表,过滤掉“登录”列中具有重复条目的行。新的 DataTable 应该与旧的具有相同的结构/列。实际上,在应用过滤器并找到一些匹配项后,只有 Rows.Count
发生变化。
到目前为止我尝试了什么
Dim distinctDT As DataTable = myDT.DefaultView.ToTable(True, "logon")
--> 只给我一个只有一列的数据表(“登录”)。虽然过滤了唯一值,但它只包含一个列 --> 如果我传入一个包含我所有列名称的数组,它不再过滤唯一值。Dim names = From row In myDataTable.AsEnumerable() Select row.Field(Of String)("Name") Distinct
--> 给我一个具有唯一值的字符串数组 --> 我需要一个与以前具有相同列的 DataTable
几个选项允许根据特定列的值过滤 DataTable 的 DataRow,以生成具有结果 DataRow 的新 DataTable。
考虑 - 既然你提到了 - selected 哪个 DataRow 并不重要,即任何 duplicate DataRow 都可以:
(如果 select 的 DataRow 在某些时候变得重要,您还可以 OrderBy()
使用另一个列的值进行分组,然后从中选择第一个或最后一个 DataRow有序 collection)
按列的值对数据行进行分组:
- 使用列的值对源 DataTable 的数据行进行分组
- Select 每个分组的第一个 DataRow
- 调用
CopyToDataTable()
方法生成新的DataTable
导致:
Dim newDt = [DataTable].AsEnumerable().
GroupBy(Function(r) r("[Column Name]")).
Select(Function(g) g.First()).
CopyToDataTable()
使用自定义 EqualityComparer:
- 构建一个简单的 EqualityComparer class 来比较两个数据行的同一列的值 objects
- 使用
Distinct()
方法并传递自定义 EqualityComparer,使用用作比较器的列的名称进行初始化 - 调用
CopyToDataTable()
方法
此方法的优点是可重用(即,您无需重建查询,只需使用要比较的列的名称初始化比较器即可)
导致:
Dim newDt = [DataTable].AsEnumerable().
Distinct(New DataRowColumnComparer("[Column Name]")).
CopyToDataTable()
自定义 EqualityComparer
:
这是一种基本的比较器。您当然可以扩展它以使用不同的索引器(表示列索引的整数或 DataColumn 引用)。
Public Class DataRowColumnComparer
Implements IEqualityComparer(Of DataRow)
Private ReadOnly t As String = String.Empty
Public Sub New(key As String)
If String.IsNullOrEmpty(key) Then Throw New ArgumentException("Empty key")
t = key
End Sub
Public Overloads Function Equals(dr1 As DataRow, dr2 As DataRow) As Boolean Implements IEqualityComparer(Of DataRow).Equals
If dr1 Is Nothing AndAlso dr2 Is Nothing Then Return True
If dr1 Is Nothing OrElse dr2 Is Nothing Then Return False
Return dr1(t).Equals(dr2(t))
End Function
Public Overloads Function GetHashCode(dr As DataRow) As Integer Implements IEqualityComparer(Of DataRow).GetHashCode
If dr(t) Is Nothing OrElse dr(t) Is DBNull.Value Then Return 0
Return dr(t).GetHashCode()
End Function
End Class