Самый простой / быстрый способ проверить, существует ли значение в DataTable in VB.net?
у меня есть DataTable
(в настоящее время с несколькими столбцами, но я мог бы просто захватить один столбец, если это делает его легче). Я хочу проверить, если String
значение существует в столбце DataTable
. (Я делаю это много раз, поэтому я хочу, чтобы это было достаточно быстро.)
какой хороший способ сделать это? Переборем DataTable
строки каждый раз кажется плохим способом. Могу ли я преобразовать столбец в flat List/Array
форматировать и использовать встроенную функцию? Что-то вроде myStrList.Contains("value")
?
4 ответов
если данные в вашей 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
, и что вам нужно сделать с найденными предметами. Лучше всего было бы попробовать каждый из них в тестовом случае и посмотреть, какой из них лучше всего подходит для того, что вам нужно.
можно использовать select
найти ли это значение или нет. Если это так,он возвращает строки или не будет. Вот пример кода, который вам поможет.
Dim foundRow() As DataRow
foundRow = dt.Select("SalesCategory='HP'")
вы должны использовать фильтр строк или DataTable.Строки.Find () вместо select (select не использует индексы). В зависимости от структуры таблицы, в частности если поле индексируется (локально), производительность в любом случае должна быть намного быстрее, чем цикл через все строки. В .NET набор полей должен быть свойства primarykey чтобы стать проиндексированы.
если ваше поле не индексируется, I избежать фильтра select и row, потому что, помимо накладных расходов сложности класса, они не предлагают проверку времени компиляции на правильность вашего условия. Если он длинный, вы можете потратить много времени на его отладку время от времени.
всегда предпочтительнее, чтобы ваш чек был строго напечатан. Сначала определив базовый тип, вы также можете определить этот вспомогательный метод, который можно преобразовать в метод расширения 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
в таблице/базе.
bool exists = dt.AsEnumerable().Where(c => c.Field<string>("Author").Equals("your lookup value")).Count() > 0;