The easiest / fastest way to check if a value exists in a DataTable on VB.net?

I have a DataTable (currently with multiple columns, but I can just grab a single column if that makes it easier). I want to check if a string value exists in a DataTable column. (I do this many times, so I want it to be fast enough.)

What is a good way to do this? Iterating through the DataTable strings seems unsuccessful every time. Is it possible to convert a column to a flat list / array format and use the built-in function? Something like myStrList.Contains("value") ?

+4
source share
4 answers

If the data in your DataTable does not change very often, and you search for the DataTable several times, and your DataTable contains many rows, then it will most likely be much faster to create your own index for the data.

The easiest way to do this is to sort the data by the key column, then to perform a binary search on the sorted list. For example, you can create an index like this:

 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 

Then you can check if the value in the index exists quickly using a binary search, for example:

 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 

You can also do the same with a simple string array. Or you can use the Dictionary object (which is the implementation of the hash table) to create the hash index of your DataTable , for example:

 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 

Then you can get the corresponding DataRow for the given key, for example:

 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 

You can also learn about using the SortedList or SortedDictionary . Both of them are binary tree implementations. It’s hard to say which of these options will be the fastest in your particular scenario. It all depends on the data type, how often you need to rebuild the index, how often you look at it, how many rows are in the DataTable , and what you need to do with the items found. It would be best to try each one in a test case and see which one is best for what you need.

+9
source

You can use select to determine if this value exists or not. If so, it returns rows or not. Here is sample code to help you.

 Dim foundRow() As DataRow foundRow = dt.Select("SalesCategory='HP'") 
+11
source

You should use a row filter or DataTable.Rows.Find () instead of select ( select does not use indexes ). Depending on your table structure, especially if the specified field is indexed (locally), the performance of any of these methods should be much faster than cyclic movement along all rows. In .NET, a set of fields must be a PrimaryKey for indexing.

If your field is not indexed, I would avoid the select and row filter, because, in addition to the overhead of class complexity, they do not offer compile-time checking for the correctness of your state. If it is long, you can spend a lot of time debugging it from time to time.

It is always advisable that your check is printed strictly. By defining a base type first, you can also define this helper method, which you can later convert to an extension method of the DataTable class:

 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 

or more general version:

 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 

and its use:

 CheckValue(myTable, Function(x) x("myColumn") = "123") 

If your string class has a MyColumn property of type String , it becomes:

 CheckValue(myTable, Function(x) x.myColumn = "123") 

One of the advantages of the above approach is that you can submit the calculated fields to your validation state, since MyColumn does not need to map the physical MyColumn in the table / database here.

+7
source
 bool exists = dt.AsEnumerable().Where(c => c.Field<string>("Author").Equals("your lookup value")).Count() > 0; 
-1
source

All Articles