Страницы: 1 2 3 След.
RSS
Фильтрация по 2000 условий
 
Цитата
New написал:
Чувствую надо Bedvit'a (Виталия) сюда подключать )P.S. А то у меня есть одна задачка, которая выполняется очень долго - удаление стоп-слов из общего списка... Общий список это 1 столбец со словами-фразами (273,000 строк), а список стоп-слов 1 столбец (2.000 строк). Макрос выполняется 3,5 минуты и меня это терзает...
Павел, если правильно понял:
Вывод списка фраз (273 000 строк), где не встречаются стоп-слова (список 2000 слов) = 11,5 секунд. Выводится примерно 271000 строк.
Файл не могу приложить, написал генератор фраз и слов.
Выкладываю код - тест.
Код
Sub TestArrayFilterVStopWord()
    Dim bVBA As Object: Set bVBA = CreateObject("BedvitCOM.VBA")
    Dim i, j, t, arrRes
    Dim testSize1 As Long: testSize1 = 273000 'строки
    Dim arrV: ReDim arrV(1 To testSize1, 1 To 1)
     
    'генерируем массив-исходник
    Cells.ClearContents
    For i = 1 To testSize1
        arrV(i, 1) = CLng(Rnd * 273000) & "Test"
    Next
    Cells(1, 1).Resize(UBound(arrV, 1), UBound(arrV, 2)) = arrV
    
    'генерируем массив условий в Excel, забираем в фильтр
    Dim arrParam: ReDim arrParam(1 To 2000, 1 To 6)
    For i = 1 To 2000
        arrParam(i, 1) = 1: arrParam(i, 3) = 1: arrParam(i, 4) = 8 + 512: arrParam(i, 5) = (i + 270000) & "T"
    Next
    Cells(1, 3).Resize(UBound(arrParam, 1), UBound(arrParam, 2)) = arrParam

    'выполняем фильтрацию по 2 тыс. условий
    t = Timer
    bVBA.ArrayFilterV arrV, arrParam, 0, arrRes 'фильтруем по первому столбцу массива (273000), НЕ содержит значения из списка(2000), выводим массив arrRes на лист(271000)
    Debug.Print Timer - t
    Cells(1, 10).Resize(UBound(arrRes, 1), UBound(arrRes, 2)) = arrRes
End Sub
«Бритва Оккама» или «Принцип Калашникова»?
 
bedvit, надо, конечно, автора послушать, но ты не думал, что твой "словарь" намного лучше тут справится?…
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Возможно, все зависит от задачи. Послушаем Павла.
«Бритва Оккама» или «Принцип Калашникова»?
 
Код
Sub TestArrayFilterVStopWord()
    Const Nm = "Поле1"
    Dim i, j, t, arrRes
    Dim testSize1 As Long: testSize1 = 273000 'строки
    Dim arrV: ReDim arrV(1 To testSize1, 1 To 1)
    'генерируем массив-исходник
    Cells.ClearContents
    arrV(1, 1) = Nm
    For i = 2 To testSize1
        arrV(i, 1) = CLng(Rnd * 273000) & "Test"
    Next
    Cells(1, 1).Resize(UBound(arrV, 1), UBound(arrV, 2)) = arrV
    'генерируем массив условий в Excel, забираем в фильтр
    Dim arrParam: ReDim arrParam(1 To 2, 1 To 2000)
    For i = 1 To 2000
        arrParam(1, i) = Nm: arrParam(2, i) = "<>" & (i + 270000) & "Test"
    Next
    Cells(1, 3).Resize(UBound(arrParam, 1), UBound(arrParam, 2)) = arrParam
 
    'выполняем фильтрацию по 2 тыс. условий
    t = Timer
    Range("A1:A" & testSize1).AdvancedFilter Action:=xlFilterCopy, _
      CriteriaRange:=Range("C1").Resize(2, 2000), CopyToRange:=Range("B1"), Unique:=False
    Debug.Print Timer - t
End Sub

50 сек. вместе с выводом результата на лист
Изменено: Ігор Гончаренко - 12.09.2022 19:24:21
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Ігор Гончаренко, эээ..нет, с такими условиями можно за доли секунды отфильтровать. Здесь фишка в том, что "СОДЕРЖИТ" слово во фразе. Я же выше сделал пример. А у вас равенство (НЕ равенство) по условию сравнивается. А нужно Like (СОДЕРЖИТ).
Ключи (2000) к фильтрации составляют только часть строки:
Код
arrParam(i, 5) = (i + 270000) & "T"
«Бритва Оккама» или «Принцип Калашникова»?
 
на словарях, без учете вывода результата на лист чуть меньше 5 сек.
Код
Sub TestArrayFilterVStopWord()
    Dim i, j, t, arrRes, dc, dr, a(), k
    Dim testSize1 As Long: testSize1 = 273000 'строки
    Dim arrV: ReDim arrV(1 To testSize1, 1 To 1)
    'генерируем массив-исходник
    Cells.ClearContents
    For i = 1 To testSize1
        arrV(i, 1) = CLng(Rnd * 273000) & "Test"
    Next
    Cells(1, 1).Resize(UBound(arrV, 1), UBound(arrV, 2)) = arrV
    'генерируем массив условий в Excel, забираем в фильтр
    Set dc = CreateObject("Scripting.Dictionary")
    Set dr = CreateObject("Scripting.Dictionary")
    For i = 1 To 2000
      dc(i + 270000 & "Test") = 0
    Next
 
    'выполняем фильтрацию по 2 тыс. условий
    t = Timer
    For i = 1 To testSize1
      If Not dc.Exists(arrV(i, 1)) Then dr(i) = arrV(i, 1)
    Next
    Set dc = Nothing
    k = dr.Items: ReDim a(0 To UBound(k), 1 To 1)
    For i = 0 To UBound(k)
      a(i, 1) = k(i)
    Next
    Debug.Print Timer - t
    Cells(1, 2).Resize(UBound(a) + 1, 1) = a
End Sub
понятно, извините, оказывается я тут свою задачу решаю((( удалить из общего списка записи содержащиеся в списке на удаление
Изменено: Ігор Гончаренко - 12.09.2022 20:25:08
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Цитата
bedvit написал:
Ігор Гончаренко , эээ..нет, с такими условиями можно за доли секунды отфильтровать.
нужно LIKE, а не равно
«Бритва Оккама» или «Принцип Калашникова»?
 
Цитата
Ігор Гончаренко написал:
чуть меньше 5 сек.
Цитата
bedvit написал:
Вывод списка фраз (273 000 строк), где не встречаются стоп-слова
Коллеги еще раз! Нужно вывести фразы, где НЕ ВСТРЕЧАЮТСЯ стоп-слова, другими словами строка НЕ СОДЕРЖИТ слово из списка!
«Бритва Оккама» или «Принцип Калашникова»?
 
Вот код генератор строк и слов (данных и условий для фильтрации)
Код
Sub TestArrayFilterVStopWord2()
    Dim bVBA As Object: Set bVBA = CreateObject("BedvitCOM.VBA")
    Dim i, j, t, arrRes
    Dim testSize1 As Long: testSize1 = 273000 'строки
    Dim arrV: ReDim arrV(1 To testSize1, 1 To 1)
      
    'генерируем массив-исходник
    Cells.ClearContents
    For i = 1 To testSize1
        arrV(i, 1) = CLng(Rnd * 273000) & "Test"
    Next
    Cells(1, 1).Resize(UBound(arrV, 1), UBound(arrV, 2)) = arrV
     
    'генерируем массив условий в Excel, забираем в фильтр
    Dim arrParam: ReDim arrParam(1 To 2000, 1 To 1)
    For i = 1 To 2000
        arrParam(i, 1) = (i + 270000) & "T"
    Next
    Cells(1, 3).Resize(UBound(arrParam, 1), UBound(arrParam, 2)) = arrParam
 
End Sub
«Бритва Оккама» или «Принцип Калашникова»?
 
Решил посмотреть сколько будет выполнятся SQL-запрос при аналогичном действии. Сравнить с DLL.
Залил таблицы из Excel, запустил.

Результат:
Дом у меня код (XLL) из первого поста отработал за 36 секунд.

SQL-запрос на SQL-сервере (дома развернут) - 3 мин 53 сек

Код
select *
from [TEST].[dbo].[table_1] as t1
left join [TEST].[dbo].[table_2] as t2 on t1.[srt] like '%'+t2.[str]+'%'
where t2.[str] is null 

Что скажут спецы по скулю?
«Бритва Оккама» или «Принцип Калашникова»?
 
Всем привет.
Да, попалась где-то задача удалить стоп-слова из общего списка по критерию "содержит", массив был большой. Я макрос написал, но меня самого не устроило время работы макроса. Вот думал прикрутить как-то словари, коллекции т.д. А то тупо идёт перебор 270,000 и каждая строка по 2000 стоп-слов перебирает через Instr(). Общее время порядка 3,5 минуты
Виталий, сейчас пытался прикрутить твой код (обновил твою библиотеку у себя, сверху есть меню Надстройки с твоими кнопочками), вот мой код, но почему-то на строке bVBA.ArrayFilterV arrV, arrParam, 0, arrRes выскакивает Runtime error 5. Что-то я видно неправильно вызываю (подсовываю свои массивы)

Файл 5мб со всеми фразами и стоп-словами выложил сюда https://disk.yandex.ru/d/xBcLbAOmODyIIg

Код
Sub TestFilterStopWords()
    Dim bVBA As Object: Set bVBA = CreateObject("BedvitCOM.VBA")
    Dim arrV As Variant, arrRes As Variant, arrParam As Variant
    Dim t As Single
      
    'массив-исходник
    arrV = Worksheets("Данные").Range("A1").CurrentRegion.Value2
     
    'массив условий
    arrParam = Worksheets("Стоп-слова").Range("A1").CurrentRegion.Value2
 
    'выполняем фильтрацию
    t = Timer
    bVBA.ArrayFilterV arrV, arrParam, 0, arrRes 'фильтруем по первому столбцу массива (273000), НЕ содержит значения из списка(2000)
    Debug.Print Timer - t
    
    With Worksheets.Add
        .Cells(1, 1).Resize(UBound(arrRes, 1), UBound(arrRes, 2)).Value = arrRes
    End With
    
    MsgBox "Затрачено времени: " & Format$((Timer - t) / 24 / 60 / 60, "nn:ss") & " sec.", vbInformation, ""
End Sub



Изменено: New - 13.09.2022 17:44:29
 
Павел залил файл сюда.

Поправил два момента:
1) Ошибка в проверке параметров.
Входящие параметры это маска из 6 элементов:
1-логические операторы (0-ИЛИ, 1-И). Для первого условия можно не указывать.
2-скобки открывающие (если нужны, можно несколько)
3-столбец для фильтрации
4-операторы сравнения (1-меньше, 2-равно, 4-больше, 8-содержит подстроку, 16-резерв(регулярки), 32- игнорировать регистр, 64-резерв(basic),  128-резерв(extended), 256 - резерв(строка с нуль символом), 512-НЕ). Бинарная маска, т.е. можно складывать, к примеру 8+512 - НЕ содержит подстроку.
5-значение для фильтра
6-скобки закрывающие (если нужны, можно несколько)

т.е. для каждого условия: И/ИЛИ,(((...,стобец, операторы, значение, ...)))
Приоритет выполнения условий: скобки, потом "И", далее "ИЛИ" (стандартно)

Т.к. условия простые, скобки пропущены.

Здесь можно посмотреть матчасть для сложных условий.

2) В тексте поправил два значения, которые начинаются с "=". Excel думал что это формула и выдавал ошибку (это не относилось к ошибке проверки параметров)
Изменено: bedvit - 13.09.2022 08:43:44
«Бритва Оккама» или «Принцип Калашникова»?
 
New,
#4 должно сработать
в диапазоне со стопсловами заменить все стопслово на <>*стопслово*
и расширенный фильтр за минуту должен управится с задачей
(я на рабочем компьютере ссылку не открою, только вечером на домашнем...)
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Цитата
bedvit написал:
Павел залил файл  сюда.
20 сек. выполнение. Интересно, почему однерки в первом столбце, ведь по логике все доолжно быть через "ИЛИ" (0)?
Изменено: testuser - 13.09.2022 09:54:38
 
У нас по условию со всеми не должно быть совпадений(вхождений). Это значит И. И это не содержит И следующую не содержит И другую не содержит.
Т.е.  столбец1 не содержит х1 and столбец1 не содержит х2 and...
Если так нагляднее, то можно и так записать
(столбец1 не содержит х1) and (столбец1 не содержит х2) and...
Изменено: bedvit - 13.09.2022 10:26:12
«Бритва Оккама» или «Принцип Калашникова»?
 
Цитата
bedvit написал:
Т.е.  столбец1 не содержит х1 and столбец1 не содержит х2 and.
Дошло. А вот стоп-лист неплохо бы почистить (как, как сделать, как изготовить, как приготовить) или опять я что-то "не вкурил"? )
Изменено: testuser - 13.09.2022 11:08:30
 
Я за стоп-лист не отвечаю :) это к New,
«Бритва Оккама» или «Принцип Калашникова»?
 
Кто-то решение от Игоря тестировал? Какой выдает результат, тайминг? К сожалению, я не могу на работе.
«Бритва Оккама» или «Принцип Калашникова»?
 
Ой как всё сложно... А через встроенный функционал не получается? Типа вот так.
 
tutochkin, попробуйте и нам расскажите)
«Бритва Оккама» или «Принцип Калашникова»?
 
Я только ближе к вечеру смогу протестировать предложенные варианты.
Да, если нужно почистить списки, то давайте почистим от знаков равно и тд. Просто какие мне данные дали, такие я и показал. Если там мусор или задвоения, давайте почистим. Меня больше интересовал механизм макроса (или других способов PQ, отдельная библиотека и тд) которые позволили бы решить данную задачу побыстрее). Решение на PQ этой задачи у меня есть
Изменено: New - 13.09.2022 11:51:29
 
New, решением-то поделитесь :) А то мы готовы ускорить :)
 
Я думаю решение от Butlochnik'a  будет сложно ускорить)
 
surkenny, у меня есть несколько решения этого задания на PQ.
Файл 5мб со всеми фразами и стоп-словами выложил сюда https://disk.yandex.ru/d/xBcLbAOmODyIIg
Изменено: New - 24.11.2023 22:48:50
 
Цитата
New: Я думаю решение от Butlochnik'a  будет сложно ускорить)
ещё есть Максим Зеленский и Андрей VG  ;)
Изменено: Jack Famous - 13.09.2022 17:34:52
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
bedvit, да, с вашей библиотекой быстро - 15,34 сек на моём компе (с выгрузкой на лист 16)
Изменено: New - 13.09.2022 18:09:55
 
New, если бы стоп-лист был списком реально СЛОВ, то можно бы было их загнать в словарь, сплитовать каждую проверяемую строку по пробелу и искать слово в словаре (при этом ещё можно пропускать подстроки короче самой короткой и длиннее самой длинной из словаря).
А вам только отобрать эти строки нужно или удалять из них эти "стоп-слова"?
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Цитата
Jack Famous написал:
А вам только отобрать эти строки нужно или удалять из них эти "стоп-слова"?
Наоборот )))
Цитата
bedvit написал:
где не встречаются стоп-слова
Скажи мне, кудесник, любимец ба’гов...
 
Цитата
New: Да, попалась где-то задача удалить стоп-слова из общего списка по критерию "содержит"
Цитата
Jack Famous: А вам только отобрать эти строки нужно или удалять из них эти "стоп-слова"?
Цитата
_Boroda_: Наоборот )))
_Boroda_, почему? Вроде же всё правильно спросил  :)

Цитата
bedvit: Вывод списка фраз (273 000 строк), где не встречаются стоп-слова
это формулировка Виталия, а задача изначально от New — он упомянул о ней в другой теме… Надо договариваться как-то  :D
Изменено: Jack Famous - 14.09.2022 09:54:43
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Есть большой список фраз, есть отдельно список стоп-слов. Нужно удалить строки из списка фраз, в которых содержатся стоп-слова
Страницы: 1 2 3 След.
Наверх