在Datagridview中查找重复项

时间:2014-02-16 13:49:17

标签: vb.net datagridview

我想在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

现在我实际上有两个问题:

  1. 由于我是初学者,我想知道这是否是搜索重复项的最佳方法

  2. 我总是得到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
    
  3. 现在我检查了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个不可见列

1 个答案:

答案 0 :(得分:0)

  1. 您需要在基础数据表中找到重复项,而不是DataGridView本身。

  2. 您当前的方法效率低下,因为它会为每一行循环所有其他行 - O(N ^ 2)。可以使用字典(字符串,行)优化到一次传递。

  3. 这是一个代码示例来说明这个想法。请注意如何使用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)
    

    将找到所有数据行的子集,至少找到一个副本,并包含所有冲突的(包括原始的)。