有没有好的方法来实现这个目标呢?每次迭代 DataTable 行似乎是一个不好的方法。我可以将该列转换为平面的 List/Array 格式,并使用内置函数吗?类似于 myStrList.Contains("value") 这样的东西?
您可以使用select
来查找值是否存在。如果存在,则返回行,否则不会返回任何结果。以下是一些示例代码以帮助您。
Dim foundRow() As DataRow
foundRow = dt.Select("SalesCategory='HP'")
如果您的DataTable
中的数据不经常更改,并且多次搜索DataTable
,且您的DataTable
包含许多行,则构建自己的数据索引可能会更快。
最简单的方法是按关键列对数据进行排序,以便您可以在已排序列表上执行二进制搜索。例如,您可以像这样构建索引:
Private Function BuildIndex(table As DataTable, keyColumnIndex As Integer) As List(Of String)
Dim index As New List(Of String)(table.Rows.Count)
For Each row As DataRow in table.Rows
index.Add(row(keyColumnIndex))
Next
index.Sort()
Return index
End Function
然后,您可以使用二进制搜索快速检查值是否存在于索引中,例如:
Private Function ItemExists(index As List(Of String), key As String) As Boolean
Dim index As Integer = index.BinarySearch(key)
If index >= 0 Then
Return True
Else
Return False
End If
End Function
您也可以使用简单的字符串数组来完成相同的事情。或者,您可以使用 Dictionary
对象(它是哈希表的一种实现)来构建您的 DataTable
的哈希索引,例如:
Private Function BuildIndex(table As DataTable, keyColumnIndex As Integer) As Dictionary(Of String, DataRow)
Dim index As New Dictionary(Of String, DataRow)(table.Rows.Count)
For Each row As DataRow in table.Rows
index(row(keyColumnIndex)) = row
Next
Return index
End Function
然后,您可以通过以下方式获取给定键的匹配 DataRow
:
Dim index As Dictionary(Of String, DataRow) = BuildIndex(myDataTable, myKeyColumnIndex)
Dim row As DataRow = Nothing
If index.TryGetValue(myKey, row) Then
' row was found, can now use row variable to access all the data in that row
Else
' row with that key does not exist
End If
您可能还希望考虑使用SortedList
或SortedDictionary
类。这两种都是二叉树的实现。很难说在您特定的情况下哪一个选项会最快。这完全取决于数据类型、索引需要多频繁进行重建、搜索频率、DataTable
中有多少行以及您需要对找到的项目做什么。最好的方法是在测试用例中尝试每个选项,看看哪个最适合您的需求。
SortedList
很好用。不知道为什么标准的 List
不起作用 - 即使字符串在列表中,它仍然返回负索引。 - DisgruntledGoat为了提高性能,应该使用row filter或DataTable.Rows.Find()而不是select(select不使用索引)。根据表格结构,特别是如果您查询的字段被索引(本地),这两种方法的性能都应比循环遍历所有行要快得多。在.NET中,一组字段需要成为PrimaryKey才能被索引。
如果您的字段没有被索引,我建议避免使用select和row filter,因为除了类复杂度的开销外,它们不能在编译时检查您的条件是否正确。如果它很长,您可能会花费大量时间调试它。
最好始终使用严格类型检查的方法。首先定义一个基础类型,然后可以定义此帮助程序方法,稍后可以将其转换为DataTable
类的扩展方法:
Shared Function CheckValue(myTable As DataTable, columnName As String, searchValue As String) As Boolean
For row As DataRow In myTable.Rows
If row(columnName) = searchValue Then Return True
Next
Return False
End Function
或者它的通用版本:
Shared Function CheckValue(myTable As DataTable, checkFunc As Func(Of DataRow, Boolean)) As Boolean
For Each row As DataRow In myTable.Rows
If checkFunc(row) Then Return True
Next
Return False
End Function
及其用法:
CheckValue(myTable, Function(x) x("myColumn") = "123")
如果您的行类有一个类型为String
的MyColumn
属性,则它变成:
CheckValue(myTable, Function(x) x.myColumn = "123")
以上方法的一个好处是,您可以将计算字段输入到检查条件中,因为这里的myColumn
不需要匹配表/数据库中的物理myColumn
。
bool exists = dt.AsEnumerable().Where(c => c.Field<string>("Author").Equals("your lookup value")).Count() > 0;