Поиск по подстроке в таблице значений. По принципу "начинается с"

07.04.21

Разработка - Универсальные функции

Часто сталкивался с задачей поиска по подстроке в таблице значений. Ну, например, в таблице нужно найти всех Петровых, или, например, все строки, в которых значение в Колонке Х начинается на "Бел". Вариантов для себя нашел всего 2. Первый - это перебор и сравнение со значением поиска, а второй - поместить во временную таблицу и через Подобно вытащить значения. Но все это было медленно, примерно на 130 000 поиск нужных значений занимал более 1,5 секунд (это перебором), а помещение во временную таблицу не всегда возможно и тоже более секунды. Тогда сделал сделал так, отсортировал таблицу по нужному мне столбцу и далее уже из этой таблицы выбирал нужные мне данные. И скорость возросла значительно, теперь то, что я ранее выбирал за 1,5 секунды, выбирается не более 10 милисекунд.

 

Часто сталкивался с задачей поиска по подстроке в таблице значений. Ну, например, в таблице нужно найти всех Петровых, или, например, все строки, в которых значение в Колонке Х начинается на "Бел". Вариантов для себя нашел всего 2. Первый - это перебор и сравнение со значением поиска, а второй - поместить во временную таблицу и через Подобно вытащить значения. Но все это было медленно, примерно на 130 000 поиск нужных значений занимал более 1,5 секунд (это перебором), а помещение во временную таблицу не всегда возможно и тоже более секунды. Тогда сделал сделал так, отсортировал таблицу по нужному мне столбцу и далее уже из этой таблицы выбирал нужные мне данные. И скорость возросла значительно, теперь то, что я ранее выбирал за 1,5 секунды, выбирается не более 10 милисекунд.

На этом абзаце мой писательский талант иссяк. Поэтому далее в телеграфном стиле.

 

Описание

Создано 2 функции.

ПоискДихотомияПоСортированнойТаблице - это основная функция, которая возвращает массив найденных строк, если ничего не найдено, то вернется пустой массив.

Параметры:

тТаблица - таблица значений, отсортированная по колонке поиска по возрастанию. 

КолонкаПоиска - Имя колонки, по которой собственно ищем, таблица тТаблица обязательно должна по ней быть отсортирована, иначе метод не работает.

ПоисковаяСтрока - строка, вхождение "слева" которой ищем в значениях колонки поиска

ТочныйПоиск - это признак того, что нужно искать одно конкретное значение. (Собственно аналог найтиСтроки, здесь он для универсальности, но вроде работает тоже побыстрее, правда я не проверял)

УчитыватьРегистр - признак того, что при сравнении значений необходимо учитывать регистр, т.е. если ищем "петр", то "Петров" не будет найден.

 

Функция ПолучитьЗначениеДляСравнения - модифицирует значение в очередной строке из Таблицы для того, чтобы его можно было сравнить с ПоисковойСтрокой.

Код функция здесь. Можно брать и вставлять в свои модули. 

Функция ПоискДихотомияПоСортированнойТаблице(тТаблица,КолонкаПоиска,ПоисковаяСтрока,ТочныйПоиск = Ложь,УчитыватьРегистр=ложь) Экспорт
    
        Результат = Новый Массив;
        ПОиск = ?(УчитыватьРегистр,ПоисковаяСтрока,ВРег(ПоисковаяСтрока));
        Длина=СтрДлина(ПОиск);    
        К = тТаблица.Количество()-1;
        нИнд = Цел(К/2);
        лево = 0;
        право = К;
        Пока Истина Цикл 
            
            нстр = тТаблица.Получить(нИнд);
            Если нИнд=лево или нИнд=право Тогда 
                Прервать;
            КонецЕсли;
            Если ПолучитьЗначениеДляСравнения(нстр,КолонкаПоиска,Длина,ТочныйПоиск,УчитыватьРегистр)=ПОиск тогда
                Прервать;
            КонецЕсли;
            
            Если ПолучитьЗначениеДляСравнения(нстр,КолонкаПоиска,Длина,ТочныйПоиск,УчитыватьРегистр)>ПОиск тогда
                право = нИнд;
                нИнд = Цел(лево+(нИнд-лево)/2);
            КонецЕсли;
            
            Если ПолучитьЗначениеДляСравнения(нстр,КолонкаПоиска,Длина,ТочныйПоиск,УчитыватьРегистр)<ПОиск тогда
                лево = нИнд;
                нИнд = Цел(право-(право -нИнд)/2);
            КонецЕсли;
            
            
            
        КонецЦикла;
        
        
        Если ПолучитьЗначениеДляСравнения(нстр,КолонкаПоиска,Длина,ТочныйПоиск,УчитыватьРегистр)=ПОиск тогда
            сч=нИнд;
            Пока ПолучитьЗначениеДляСравнения(нстр,КолонкаПоиска,Длина,ТочныйПоиск,УчитыватьРегистр)=ПОиск Цикл
                Результат.Вставить(0,нстр); 
                сч=сч-1;
                Если сч<0 Тогда 
                    Прервать;
                КонецЕсли;
                нстр = тТаблица.Получить(сч);
                
            КонецЦикла;
            сч=нИнд+1;
            Если сч<=К Тогда 
                нстр = тТаблица.Получить(сч);
                Пока ПолучитьЗначениеДляСравнения(нстр,КолонкаПоиска,Длина,ТочныйПоиск,УчитыватьРегистр)=ПОиск Цикл 
                    Результат.Добавить(нстр);
                    сч=сч+1;
                    Если сч>К Тогда 
                        Прервать;
                    КонецЕсли;
                    нстр = тТаблица.Получить(сч);
                    
                КонецЦикла;
                
            КонецЕсли;
        КонецЕсли;
        
        Возврат Результат;

    
    
    
    
КонецФункции

Функция ПолучитьЗначениеДляСравнения(СтрокаТаблицы,КолонкаПоиска,КоличествоСимволовПоиска,ТочноеСовпадение,УчитыватьРегистр)
    
    Если ТочноеСовпадение Тогда 
        Результат = ?(УчитыватьРегистр,СтрокаТаблицы[КолонкаПоиска],ВРег(СтрокаТаблицы[КолонкаПоиска]));
    иначе
        Результат = ?(УчитыватьРегистр,Лев(СтрокаТаблицы[КолонкаПоиска],КоличествоСимволовПоиска),Лев(ВРег(СтрокаТаблицы[КолонкаПоиска]),КоличествоСимволовПоиска));
    КонецЕсли;
    Возврат Результат;
    
КонецФункции

 

Как можно использовать

 

 Например, у нас есть таблица

ФИО Оклад
Иванов Иван Иванович 600
Петров Иван Иванович 300
петров Николай Петрович 700
сидоров Иван Иванович 400


Нам нужно выбрать всех Петровых.

Сначала мы сортируем таблицу по ФИО. Желательно этот метод применять таким образом, что таблица отсортирована один раз, а сам метод применяется много раз.

А далее

РезультатМассивСтрок = ПоискДихотомияПоСортированнойТаблице(таблицаСФИО,"ФИО","петров ",ложь,ложь);

В итоге в результатМассив попадут строки.

ФИО Оклад
Петров Иван Иванович 300
петров Николай Петрович 700

 

Я например этот метод использовал для автоподстановки в поле ввода. (таблица была более 130000 строк).

Послесловие

Коллеги, жду от Вас комментарии. А может, кто-то знает более быстрый метод, а я тут изобретаю велосипед.

 

ТаблицаЗначений таблица поиск дихотомия

См. также

Универсальные функции Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Благодаря этим пяти строчкам можно больше не заморачиваться с загрузкой из внешних файлов. Пользуюсь везде, всегда и постоянно.

21.05.2024    20244    dimanich70    81    

145

Универсальные функции Программист Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Задача: вставить картинку из буфера обмена на форму средствами платформы 1С.

1 стартмани

18.03.2024    4100    3    John_d    11    

57

Универсальные функции Программист Стажер Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Пришлось помучиться с GUID-ами немного, решил поделиться опытом, мало ли кому пригодится.

12.02.2024    18209    atdonya    24    

57

Универсальные функции Программист Платформа 1С v8.3 Бесплатно (free)

На заключительных этапах, когда идет отладка или доработка интерфейса, необходимо много раз переоткрыть внешний объект. Вот один из способов автоматизации этого.

30.11.2023    5511    ke.92@mail.ru    16    

65

WEB-интеграция Универсальные функции Механизмы платформы 1С Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

При работе с интеграциями рано или поздно придется столкнуться с получением JSON файлов. И, конечно же, жизнь заставит проверять файлы перед тем, как записывать данные в БД.

28.08.2023    14778    YA_418728146    7    

166

Пакетная печать Печатные формы Адаптация типовых решений Универсальные функции Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Россия Абонемент ($m)

Расширение для программ 1С:Управление торговлей, 1С:Комплексная автоматизация, 1С:ERP, которое позволяет распечатывать печатные формы для непроведенных документов. Можно настроить, каким пользователям, какие конкретные формы документов разрешено печатать без проведения документа.

2 стартмани

22.08.2023    3594    57    progmaster    8    

4

Инструментарий разработчика Универсальные функции Платформа 1С v8.3 Конфигурации 1cv8 1С:Розница 2 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Зарплата и Управление Персоналом 3.x Абонемент ($m)

Копирует в буфер значения из списков, из ячеек отчетов, таблиц, настроек списков, других отборов и вставляет в выбранную настройку отбора. Работает с Объект не найден. Работает как в одной так и между разными базами 1С. Использует комбинации [Alt+C] Копировать список, [Alt+V] Вставить список. Также для копирования данных используется стандартная [Ctrl+C] (например из открытого xls, mxl, doc и т.п. файла скопировать список наименований)

1 стартмани

13.10.2022    18500    171    sapervodichka    112    

135
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. Activity 07.04.21 13:42 Сейчас в теме
Так в данном случае получается поиск не по подстроке, а именно по началу строки или точному соответствию значения и строки поиска, что расходится с понятием поиск по подстроке

Или я ошибаюсь?
2. MikeI 73 07.04.21 18:31 Сейчас в теме
(1)
Так в данном случае получается поиск не по подстроке, а именно по началу строки или точному соответствию значения и строки поиска, что расходится с понятием поиск по подстроке
.

Начало строки - это частный случай подстроки, поэтому я в заголовке и уточнил способ поиска, что бы не создавалось ложное ощущение что поиск происходит по любой подстроке
3. TMV 14 08.04.21 13:13 Сейчас в теме
Ну т.е. достаточно было отсортировать значения в колонке?
4. MikeI 73 08.04.21 14:06 Сейчас в теме
(3)Вы про пример? В статье таблица некорректно показана, она конечно должна быть отсортирована по колонке ФИО. Просто когда не 4 записи , а 100 000 эффект перед обычным перебором налицо.
5. Cyberhawk 135 10.04.21 20:35 Сейчас в теме
на 130 000 поиск нужных значений занимал более 1,5 секунд
В какой момент инициализируется такая ТЗ?
6. MikeI 73 11.04.21 13:30 Сейчас в теме
(5) Таблица инициализируется и сортируется один раз до начала многократного применения процедуры. Я например ее использовал для динамического формирования списка выбор в элементе
7. Cyberhawk 135 11.04.21 14:27 Сейчас в теме
(6) А что является источником данных для формирования ТЗ такого размера? Данные выбираются из какой-то таблицы БД?
8. MikeI 73 11.04.21 14:32 Сейчас в теме
(7) Сторонние данные. Например получение данных с какого-нибудь сайт. Когда значения нужны, а но не нужно записывать их в базу данных 1С. Для пример список Брендов на ОЗОНе.
9. Cyberhawk 135 11.04.21 14:49 Сейчас в теме
(8) А получение с сайта ста тысяч строк (полагаю, как минимум состоящих из пары "ИД - представление") быстро происходит?
Это делается ХТТП-запросом?
10. MikeI 73 11.04.21 14:53 Сейчас в теме
(9) Нет это не быстро. Но это уже данность, и получается один раз. А далее много много раз используется поиск значений полученной таблице. Например Http-запросом
11. Cyberhawk 135 11.04.21 14:58 Сейчас в теме
(10) А источник данных (сайт) не предоставляет возможность получать данные, удовлетворяющие отбору?
12. MikeI 73 11.04.21 15:03 Сейчас в теме
(11) Во-первых. Я привел для примера какие данные, могут. А так это может быть любая таблица значений , полученная любыми способами. А во вторых , получение данных сайта будет происходить дольше, если мы х ним обращаемся много раз, нежели чем при выборке максимального количества данных за один раз.
13. Cyberhawk 135 11.04.21 15:33 Сейчас в теме
(12)
это может быть любая таблица значений , полученная любыми способами
Интересовал конкретный сценарий, в котором пользователю может понадобиться ТЗ на 100+ тысяч строк.
получение данных сайта будет происходить дольше, если мы х ним обращаемся много раз, нежели чем при выборке максимального количества данных за один раз
А сколько в среднем операций поиска выполняет пользователь по такой большой ТЗ? И как реализовано удерживание ТЗ в памяти в течение времени жизни сеанса пользователя?
14. MikeI 73 11.04.21 15:58 Сейчас в теме
(13)
И как реализовано удерживание ТЗ в памяти в течение времени жизни сеанса пользователя?
средствами платформы.

Про сценарий - Например выбор бренда из списка более 130 тыс. с помощью ввода начальных символов бренда. Динамически формируется список выбора
15. pentanom 25 18.01.22 13:03 Сейчас в теме
А Петрович тоже попадает в выборку?
16. slicem 9 19.01.23 11:20 Сейчас в теме
Блин! Идея сравнивать строки на больше меньше - шикарная. Никогда бы не додумался. Спасибо.
17. user1656634 01.02.23 15:49 Сейчас в теме
Функции помогли решить важную задачу по поиску нужного значения в строке, СПАСИБО!

Только хотел уточнить действие строки
нИнд = Цел(К/2);


из за деления на 2 последнюю и нечетную строку функция не видит.
18. MikeI 73 04.02.23 19:23 Сейчас в теме
С граничными значениями действительно были проблемы. А вот с нечётной строкой, рано или поздно найдется значение когда останется 2 значения
Оставьте свое сообщение