我有DataTable
(目前有多列,但如果它更容易,我可以抓住一列)。我想检查String
的列中是否存在DataTable
值。 (我这么做很多次,所以我希望它的速度相当快。)
这样做的好方法是什么?每次迭代DataTable
行似乎都是一种糟糕的方式。我可以将列转换为平面List/Array
格式,并使用内置函数吗?像myStrList.Contains("value")
?
答案 0 :(得分:13)
您可以使用select
来查找该值是否存在。如果是这样,它返回行或不会。这里有一些示例代码可以帮助您。
Dim foundRow() As DataRow
foundRow = dt.Select("SalesCategory='HP'")
答案 1 :(得分:10)
如果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
中有多少行,以及您需要对找到的项目执行的操作。最好的办法是在测试用例中尝试每一个,看看哪个最适合你需要的。
答案 2 :(得分:8)
您应该使用row filter或DataTable.Rows.Find()代替select(select does not use indexes)。根据您的表结构,特别是,如果您的字段已编入索引(本地),则任何一种方式的性能都应比循环遍历所有行的速度快得多。在.NET中,一组字段需要是PrimaryKey才能被编入索引。
如果您的字段没有编入索引,我会避免使用select和row过滤器,因为除了类复杂性的开销之外,它们不提供编译时间检查以确定您的条件是否正确。如果它很长,你最终可能会花很多时间调试它。
最好是严格打字。首先定义了一个底层类型,你也可以定义这个helper方法,你可以在以后转换为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")
如果您的行类具有MyColumn
类型的String
属性,则它变为:
CheckValue(myTable, Function(x) x.myColumn = "123")
上述方法的一个好处是,您可以将计算字段输入检查条件,因为此处myColumn
不需要与表/数据库中的物理myColumn
匹配。 / p>
答案 3 :(得分:-1)
bool exists = dt.AsEnumerable().Where(c => c.Field<string>("Author").Equals("your lookup value")).Count() > 0;