我想在dgv中搜索重复项,并在列表中收集重复项的行号(如有必要,将其显示给用户)。这是我的代码:
Function Check(ByVal dgv As DataGridView)
Dim Duplicates As New List(Of Tuple(Of Integer, Integer))
For i As Integer = 1 To dgv.RowCount
For k As Integer = 1 To dgv.RowCount
For j As Integer = 1 To dgv.ColumnCount
Dim l As Integer
If dgv.Rows(i).Cells(j).Value = dgv.Rows(k + 1).Cells(j).Value Then
l += l + 1
If l = dgv.ColumnCount Then
Duplicates.Add(Tuple.Create(i, k))
End If
End If
Next
Next
Next
Return Duplicates
End Function
现在我实际上有两个问题:
由于我是初学者,我想知道这是否是搜索重复项的最佳方法
我总是得到Operator '=' is not defined for type 'DBNull'
的错误。我知道错误,但不知道如何处理它。我试过了:
Dim l As Integer
'DbNull - Check
Dim first As String
If IsDBNull(dgv.Rows(i).Cells(j).Value) Then
first = 0
Else
first = dgv.Rows(i).Cells(j).Value
End If
现在我检查了first = second
而不是dgv.Rows(i).Cells(j).Value = dgv.Rows(k + 1).Cells(j).Value
但是现在我遇到了类型问题,因为db-types是Date,varchar,integer等等,这让我与{{1 }}。有人知道摆脱错误的方法吗?
其他信息: 我的dgv - 绑定到连接到sql server的数据表 - 有6个可见列和4个不可见列
答案 0 :(得分:0)
您需要在基础数据表中找到重复项,而不是DataGridView本身。
您当前的方法效率低下,因为它会为每一行循环所有其他行 - O(N ^ 2)。可以使用字典(字符串,行)优化到一次传递。
这是一个代码示例来说明这个想法。请注意如何使用keyColumns
hashset来指定应使用哪些列来确定重复项(也称为唯一键)。
Dim dt As New DataTable
dt.Columns.Add("col1")
dt.Columns.Add("col2")
dt.Columns.Add("col3")
dt.Rows.Add({"val1", "val2", "val3"})
dt.Rows.Add({"val1", "val3", "val3"})
dt.Rows.Add({"val1", "val3", "val4"})
Dim dict As New Dictionary(Of String, List(Of DataRow))
Dim keyColumns As New HashSet(Of String)({"col1", "col3"})
For Each dr As DataRow In dt.Rows
Dim sbKey As New System.Text.StringBuilder
For Each col As DataColumn In dt.Columns
Dim colName As String = col.ColumnName
If Not keyColumns.Contains(colName) Then Continue For
Dim colValue As String = dr.Field(Of String)(colName)
sbKey.Append(colValue & "@")
Next
Dim key As String = sbKey.ToString
Dim drList As List(Of DataRow) = Nothing
If Not dict.TryGetValue(key, drList) Then
drList = New List(Of DataRow)
dict.Add(key, drList)
End If
drList.Add(dr)
Next
最后,您的dict
包含按键组织的所有数据行的字典。每个键中有1个条目的那些没有重复项。其他人是重复的。您可以进一步调整它以仅查找具有N个重复项(N> = 1)的行,因此,例如:
Dim p = dict.Where(Function(x) x.Value.Count > 1)
将找到所有数据行的子集,至少找到一个副本,并包含所有冲突的(包括原始的)。