Моё почтение, джентльмены!
Готов инструмент фильтрации массива с любым количеством столбцов, по любым условиям.
ArrayFilterV(VARIANT* array_in, VARIANT* array_parameters, VARIANT_BOOL array_out_index, VARIANT* array_out)
1. array_in - массив входящий (одномерный, двухмерный)
2. array_parameters - массив задаваемых параметров (6 параметров для любого столбца, можно для одного и того же, можно для разных). Количество условий не ограничено. Можно создать самому из списка, можно создать двухмерный массив и заполнить, можно забрать сразу с листа Excel.
3. array_out_index - режим вывода: 0- отфильтрованный массив, 1-массив индексов
4. array_out - массив результатов
Условия в массиве параметров применяются в том же порядке, что и везде. Приоритет скобки, потом "И" и "ИЛИ" (одинаковый приоритет, выполняются в порядке следования)
Параметры массива условий (сделал максимально просто для пользователя):
1-логические операторы (0-ИЛИ, 1-И)
2-скобка открывающая
3-столбец для фильтрации
4-операторы сравнения (//1-меньше, 2-равно, 4-больше, 8-содержит подстроку, 16-резерв(регулярки), 32- игнорировать регистр, 64-резерв(basic), 128-резерв(extended), 256 - LIKE (пока с символом подстановки "*"), 512-НЕ)
5-значение для фильтра
6-скобка закрывающая,
Условия можно задавать как простые:
'фильтр по первому столбцу, значение = 9
Array(, , 1, Равно, 9, "")

так и более сложные, к примеру выше
Array(, "(((", 1, Содержит, "маша", , ИЛИ, , 1, Содержит, "вася", ")", И, , 1, НеРавно, "маша иванова", ")", ИЛИ, "(", 2, НеРавно, "'1", , ИЛИ, , 2, Равно, 1, "))", И, "(", 3, БольшеРавно, 12.5, , И, , 3, МеньшеРавно, 55.8, ")")
или в таком виде (как удобнее)
Array( _
, "(((", 1, Содержит, "маша", , _
ИЛИ, , 1, Содержит, "вася", ")", _
И, , 1, НеРавно, "маша иванова", ")", _
ИЛИ, "(", 2, НеРавно, "'1", , _
ИЛИ, , 2, Равно, 1, "))", _
И, "(", 3, БольшеРавно, 12.5, , _
И, , 3, МеньшеРавно, 55.8, ")" _
)
ArrayFilterV поиск по 10млн. строк с найденными 5 млн. - 4 сек.
В улучшенном варианте (1 этап оптимизации) - 1,76 сек.
Оптимизированный вариант: вывод отфильтрованного массива 5 млн строк (изначальный 10 млн) = 0,25 секунд
вывод массива индексов 5 млн строк (изначальный 10 млн) = 0,17 секунд
Простой пример (с замером скорости на 10 млн строк) и сложный (с выводом условий и результата):
Выложил и релизы библиотек на .
Готов инструмент фильтрации массива с любым количеством столбцов, по любым условиям.
ArrayFilterV(VARIANT* array_in, VARIANT* array_parameters, VARIANT_BOOL array_out_index, VARIANT* array_out)
1. array_in - массив входящий (одномерный, двухмерный)
2. array_parameters - массив задаваемых параметров (6 параметров для любого столбца, можно для одного и того же, можно для разных). Количество условий не ограничено. Можно создать самому из списка, можно создать двухмерный массив и заполнить, можно забрать сразу с листа Excel.
3. array_out_index - режим вывода: 0- отфильтрованный массив, 1-массив индексов
4. array_out - массив результатов
Условия в массиве параметров применяются в том же порядке, что и везде. Приоритет скобки, потом "И" и "ИЛИ" (одинаковый приоритет, выполняются в порядке следования)
Параметры массива условий (сделал максимально просто для пользователя):
1-логические операторы (0-ИЛИ, 1-И)
2-скобка открывающая
3-столбец для фильтрации
4-операторы сравнения (//1-меньше, 2-равно, 4-больше, 8-содержит подстроку, 16-резерв(регулярки), 32- игнорировать регистр, 64-резерв(basic), 128-резерв(extended), 256 - LIKE (пока с символом подстановки "*"), 512-НЕ)
5-значение для фильтра
6-скобка закрывающая,
Условия можно задавать как простые:
'фильтр по первому столбцу, значение = 9
Array(, , 1, Равно, 9, "")
так и более сложные, к примеру выше
Array(, "(((", 1, Содержит, "маша", , ИЛИ, , 1, Содержит, "вася", ")", И, , 1, НеРавно, "маша иванова", ")", ИЛИ, "(", 2, НеРавно, "'1", , ИЛИ, , 2, Равно, 1, "))", И, "(", 3, БольшеРавно, 12.5, , И, , 3, МеньшеРавно, 55.8, ")")
или в таком виде (как удобнее)
Array( _
, "(((", 1, Содержит, "маша", , _
ИЛИ, , 1, Содержит, "вася", ")", _
И, , 1, НеРавно, "маша иванова", ")", _
ИЛИ, "(", 2, НеРавно, "'1", , _
ИЛИ, , 2, Равно, 1, "))", _
И, "(", 3, БольшеРавно, 12.5, , _
И, , 3, МеньшеРавно, 55.8, ")" _
)
ArrayFilterV поиск по 10млн. строк с найденными 5 млн. - 4 сек.
В улучшенном варианте (1 этап оптимизации) - 1,76 сек.
Оптимизированный вариант: вывод отфильтрованного массива 5 млн строк (изначальный 10 млн) = 0,25 секунд
вывод массива индексов 5 млн строк (изначальный 10 млн) = 0,17 секунд
Простой пример (с замером скорости на 10 млн строк) и сложный (с выводом условий и результата):
| Код |
|---|
Option Explicit
'операторы (aliases) псевдонимы
Const ИЛИ = 0, И = 1, РАВНО = 2, СОДЕРЖИТ = 8, НЕРАВНО = 512 + 2, МЕНЬШЕРАВНО = 1 + 2, БОЛЬШЕРАВНО = 4 + 2, МЕНЬШЕ = 1, БОЛЬШЕ = 4
'ОДНОМЕРНЫЙ МАССИВ, ПРОСТЫЕ УСЛОВИЯ
Sub TestArrayFilterV_1()
'Dim bVBA As New BedvitCOM.VBA 'раннее связывание
Dim bVBA As Object: Set bVBA = CreateObject("BedvitCOM.VBA") 'позднее связывание
Dim arrResult
'первоначальный массив данных
Dim arrV: arrV = Array(1, 0, 1, 0, 1, 0)
'массив условий (фильтр по первому столбцу, значение = 1)
Dim p: p = Array(, , 1, РАВНО, 1, "")
' фильтруем ===============================
bVBA.ArrayFilterV arrV, p, 0, arrResult
'========================================
Debug.Print UBound(arrResult) + 1 'начало с 0
End Sub
'ДВУХМЕРНЫЙ МАССИВ, ПРОСТЫЕ УСЛОВИЯ
Sub TestArrayFilterV_2()
'Dim bVBA As New BedvitCOM.VBA 'раннее связывание
Dim bVBA As Object: Set bVBA = CreateObject("BedvitCOM.VBA") 'позднее связывание
Dim arrResult, r, c, t, x
Dim sizeRow As Long: sizeRow = 10000000
Dim sizeCol As Long: sizeCol = 1
Dim arrV: ReDim arrV(1 To sizeRow, 1 To sizeCol) 'первоначальный массив данных, далее хаполняем рендомно
'массив условий (фильтр по первому столбцу, значение = 1)
Dim p: p = Array(, , 1, РАВНО, 1, "")
'заполняем первоначальный массив с данными
For r = 1 To sizeRow
For c = 1 To sizeCol
arrV(r, c) = CLng(Rnd * 2)
Next
Next
t = Timer
' фильтруем ===============================
bVBA.ArrayFilterV arrV, p, 0, arrResult
'========================================
Debug.Print Timer - t
Debug.Print UBound(arrResult) + 1 'начало с 0
End Sub
'ДВУХМЕРНЫЙ МАССИВ, СЛОЖНЫЕ УСЛОВИЯ
Sub TestArrayFilterV_3()
Dim arrParam, arrTest, arrRes, bCOMvba As Object: Set bCOMvba = CreateObject("BedvitCOM.VBA")
Cells.ClearContents
'создаем тестовый массив
arrTest = Array("маша иванова", "'1", 13, "маша иванова", 1, 13, "маша", "'1", 14, "вася", "'1", 14, "паша", 1, 50, "вася", 2, 52, "маша", 1, 60, "вася", 1, 65)
bCOMvba.Array1Dto2D arrTest, 1, 1, UBound(arrTest) / 3: bCOMvba.Transpose arrTest
Cells(1, 1).Resize(UBound(arrTest, 1), UBound(arrTest, 2)) = arrTest
'запись условий для фильтра:(((c1 like "маша" or like "вася") and c1<>"маша иванова") or (c2<>"1" or c2=1)) and (c3>=12,5 and c3<=55,8)
arrParam = Array(, "(((", 1, СОДЕРЖИТ, "маша", , ИЛИ, , 1, СОДЕРЖИТ, "вася", ")", И, , 1, НЕРАВНО, "маша иванова", ")", ИЛИ, "(", 2, НЕРАВНО, "'1", , ИЛИ, , 2, РАВНО, 1, "))", И, "(", 3, БОЛЬШЕРАВНО, 12.5, , И, , 3, МЕНЬШЕРАВНО, 55.8, ")")
'ИЛИ ТАК
arrParam = Array( _
, "(((", 1, СОДЕРЖИТ, "маша", , _
ИЛИ, , 1, СОДЕРЖИТ, "вася", ")", _
И, , 1, НЕРАВНО, "маша иванова", ")", _
ИЛИ, "(", 2, НЕРАВНО, "'1", , _
ИЛИ, , 2, РАВНО, 1, "))", _
И, "(", 3, БОЛЬШЕРАВНО, 12.5, , _
И, , 3, МЕНЬШЕРАВНО, 55.8, ")" _
)
bCOMvba.Array1Dto2D arrParam, 1, 1, UBound(arrParam) / 6: bCOMvba.Transpose arrParam
Cells(1, 5).Resize(UBound(arrParam, 1), UBound(arrParam, 2)) = arrParam
'применяем фильтр
bCOMvba.ArrayFilterV arrTest, arrParam, 0, arrRes
Cells(1, 12).Resize(UBound(arrRes, 1), UBound(arrRes, 2)) = arrRes
End Sub
|
Выложил и релизы библиотек на .
Изменено: - 21.09.2022 11:24:11
«Бритва Оккама» или «Принцип Калашникова»?