Как реализовать поиск и генерацию визуально схожих слов (омоглифов) в 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В практике программирования на платформе 1С часто возникает задача поиска визуальных дублей. Это ситуация, когда пользователи вводят данные (например, артикулы или наименования номенклатуры), смешивая кириллицу и латиницу. Внешне слова «АH0» (русская А, латинская H, цифра 0) и «AHО» (латинская A, латинская H, русская О) выглядят идентично, но для системы это абсолютно разные строки. Разберем, как построить алгоритм, который поможет найти все возможные вариации написания слова на основе похожих символов.

Анализ проблемы: что такое омоглифы

Омоглифы — это символы, которые имеют разное кодирование в Unicode, но выглядят одинаково или очень похоже. Для решения нашей задачи нам в первую очередь необходимо составить карту соответствий. Проанализируем основные группы символов, которые чаще всего путают:

  1. Заглавные буквы: А-A, В-B, С-C, Е-E, Н-H, К-K, М-M, О-O, Р-P, Т-T, Х-X, У-Y.
  2. Строчные буквы: а-a, с-c, е-e, о-o, р-p, х-x, у-y.
  3. Цифры и буквы: 0 (ноль) и О (буква), 3 (три) и З (буква), 6 (шесть) и б (буква).

Важно помнить, что функция КодСимвола() в 1С вернет разные значения для русской «А» (1040) и латинской «A» (65). На этом и строится логика программного поиска.

Шаг 1: Подготовка таблицы соответствий

Первым делом нам нужно создать объект Соответствие, в котором мы укажем пары похожих знаков. Рассмотрим, как инициализировать такую структуру данных на сервере. Мы будем использовать универсальный подход, где ключом является один символ, а значением — массив или строка всех его возможных визуальных аналогов.


&НаСервере
Функция ПолучитьТаблицуСходства()
    Сходство = Новый Соответствие;
    // Добавляем пары: Символ -> Список замен
    Сходство.Вставить("А", "A"); // Русская А и Латинская A
    Сходство.Вставить("A", "А");
    Сходство.Вставить("О", "0O"); // Русская О -> Цифра 0 и Латинская O
    Сходство.Вставить("0", "ОO"); // Цифра ноль -> Русская О и Латинская O
    Сходство.Вставить("Р", "P"); // Русская Р и Латинская P
    Сходство.Вставить("Н", "H"); // Русская Н и Латинская H
    // И так далее для всех пар...
    Возврат Сходство;
КонецФункции

Шаг 2: Рекурсивный перебор комбинаций

Основная сложность заключается в том, что в слове может быть несколько заменяемых символов. Если у нас слово из 3 букв и у каждой по 2 варианта написания, мы получим 2 в кубе (8) комбинаций. Для решения такой задачи идеально подходит рекурсия. Проанализируем алгоритм: мы берем первый символ, находим для него все варианты, и для каждого варианта вызываем эту же функцию для оставшейся части строки.

Рассмотрим пример реализации функции генерации вариантов:


&НаСервере
Процедура СгенерироватьВарианты(Знач ТекущийПрефикс, Знач ОставшаясяЧасть, ТаблицаСходства, СписокРезультатов)
    
    Если СтрДлина(ОставшаясяЧасть) = 0 Тогда
        СписокРезультатов.Добавить(ТекущийПрефикс);
        Возврат;
    КонецЕсли;

    // Выделяем первый символ из текущего остатка
    ПервыйСимвол = Лев(ОставшаясяЧасть, 1);
    Хвост = Сред(ОставшаясяЧасть, 2);

    // 1. Добавляем вариант с оригинальным символом
    СгенерироватьВарианты(ТекущийПрефикс + ПервыйСимвол, Хвост, ТаблицаСходства, СписокРезультатов);

    // 2. Ищем замены для этого символа
    ВариантыЗамены = ТаблицаСходства.Получить(ВРег(ПервыйСимвол));
    Если ВариантыЗамены <> Неопределено Тогда
        Для НомерСимвола = 1 По СтрДлина(ВариантыЗамены) Цикл
            СимволЗамены = Сред(ВариантыЗамены, НомерСимвола, 1);
            
            // Сохраняем регистр (если оригинал был маленьким, делаем замену маленькой)
            Если ПервыйСимвол = НРег(ПервыйСимвол) Тогда
                СимволЗамены = НРег(СимволЗамены);
            КонецЕсли;
            
            СгенерироватьВарианты(ТекущийПрефикс + СимволЗамены, Хвост, ТаблицаСходства, СписокРезультатов);
        КонецЦикла;
    КонецЕсли;

КонецПроцедуры

Шаг 3: Вывод данных в таблицу на форме

Чтобы пользователь мог увидеть результат, создадим команду на форме, которая будет считывать значение из поля ввода и заполнять ТаблицаЗначений. Выясним, как правильно организовать этот процесс, чтобы исключить дубликаты в итоговом списке (так как рекурсия может породить одинаковые строки, если в таблице соответствий есть пересечения).


&НаКлиенте
Процедура ОбработатьСлово(Команда)
    РезультатМассив = ОбработатьСловоНаСервере(Объект.ВведенноеСлово);
    Объект.ТаблицаВариантов.Очистить();
    Для Каждого Вариант Из РезультатМассив Цикл
        НоваяСтрока = Объект.ТаблицаВариантов.Добавить();
        НоваяСтрока.Значение = Вариант;
    КонецЦикла;
КонецПроцедуры

&НаСервере
Функция ОбработатьСловоНаСервере(ИсходноеСлово)
    ТаблицаСходства = ПолучитьТаблицуСходства();
    СписокРезультатов = Новый СписокЗначений;
    
    СгенерироватьВарианты("", ИсходноеСлово, ТаблицаСходства, СписокРезультатов);
    
    // Удаляем дубликаты через массив и вспомогательный объект
    УникальныеВарианты = Новый Соответствие;
    Для Каждого Элемент Из СписокРезультатов Цикл
        УникальныеВарианты.Вставить(Элемент.Значение, Истина);
    КонецЦикла;
    
    МассивРезультат = Новый Массив;
    Для Каждого КлючИЗначение Из УникальныеВарианты Цикл
        МассивРезультат.Добавить(КлючИЗначение.Ключ);
    КонецЦикла;
    
    Возврат МассивРезультат;
КонецФункции

Оптимизация и визуальное оформление

Для того чтобы сделать результат более наглядным (как просил автор темы), мы можем использовать Условное оформление на управляемой форме. Однако, поскольку в 1С нельзя раскрасить разные буквы внутри одной ячейки текста, рассмотрим альтернативные методы:

Практическое применение алгоритма

Рассмотрим ситуации, где данный код будет наиболее полезен:

  1. Поиск дублей в справочнике Номенклатура: Перед записью нового элемента можно генерировать все варианты его написания и проверять, нет ли уже в базе товара с таким «визуальным» именем.
  2. Интеграция с внешними системами: При загрузке данных из Excel, где менеджеры часто ошибаются в раскладке, этот алгоритм позволит автоматически сопоставлять позиции.
  3. Защита артикулов: В системах складского учета (WMS) использование подобных алгоритмов предотвращает ошибки при сканировании штрихкодов, содержащих похожие символы.

Таким образом, мы разобрали полноценное решение задачи перебора символов. Использование Соответствие для хранения омоглифов и рекурсивного метода для построения комбинаций позволяет эффективно находить скрытые ошибки в текстовых данных информационной базы 1С.

← На главную