Функция Русский MetaPhone для 1С:Предприятия любой платформы и конфигурации

14.05.10

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

Функция полезна для организации поиска информации в базе данных по нечёткому совпадению.

Данная функция была портирована с Visual Basic несколько лет назад, в ходе решения задачи по поиску контрагентов или физлиц (уже не помню) по нечёткому совпадению.
Обнаружил случайно, копаясь в старых работах на платформе 7.7, и решил выложить в надежде, что кому-нибудь пригодится.  Хочу заметить, что для платформы 8.1 может быть неактуально, в связи со штатными возможностями нечёткого поиска.

Оригинал функции и статья по теме находились по адресу «Как ваша фамилия», или Русский MetaPhone (сейчас там error 404, выложил здесь)

//________________________________________________________________________
//
// ** MetaPhone() algorithm **
// ** coded by Sergey (aka Porutchik) * 2006 http://forum.aeroion.ru
//
// based on description :
// © Peter Kankowski, 2002
// http://www.kankowski.narod.ru/dev/metaphoneru.htm
//
Функция  MetaPhoneRu(Знач W) Экспорт
   
//Заменяет ЙО, ЙЕ и др.; неплохо оптимизирован.

    //alf - алфавит кроме исключаемых букв, cns1 и cns2 - звонкие и глухие
    //согласные, cns3 - согласные, перед которыми звонкие оглушаются,
    //  ch, ct - образец и замена гласных
   
alf = "ОЕАИУЭЮЯПСТРКЛМНБВГДЖЗЙФХЦЧШЩЁЫ";
   
cns1 = "БЗДВГ";
   
cns2 = "ПСТФК";
   
cns3 = "ПСТКБВГДЖЗФХЦЧШЩ";
   
ch = "ОЮЕЭЯЁЫ";
   
ct = "АУИИАИА";
   
//S, V - промежуточные строки, i - счётчик цикла, B - позиция
    //найденного элемента, c$ - текущий символ, c_old$ - предыдущий символ
   
S= "";
   
V= "";
   
i= 0;
   
B= 0;
   
c= "";
   
old_c = "";

   
//Переводим в верхний регистр, оставляем только
    //символы из alf и копируем в S:
   
W = Врег(W);
    Для
i = 1 По СтрДлина(W) Цикл
       
c = Сред(W, i, 1);
        Если
Найти(alf, c) > 0 Тогда
           
S = S + c;
        КонецЕсли;
    КонецЦикла;
    Если
СтрДлина(S) = 0 Тогда
        Возврат
"";
    КонецЕсли;

   
//Сжимаем окончания:
   
Врем = Прав(S, 6);
    Если
Врем = "ОВСКИЙ"  Тогда
       
S = Лев(S, СтрДлина(S) - 6) + "@";
    ИначеЕсли
Врем = "ЕВСКИЙ" Тогда
       
S = Лев(S, СтрДлина(S) - 6) + "#";
    ИначеЕсли
Врем = "ОВСКАЯ" Тогда
       
S = Лев(S, СтрДлина(S) - 6) + "$";
    ИначеЕсли
Врем = "ЕВСКАЯ" Тогда
       
S = Лев(S, СтрДлина(S) - 6) + "%";
    Иначе
       
Врем = Прав(S, 4);
        Если (
Врем = "ИЕВА") ИЛИ (Врем = "ЕЕВА") Тогда
           
S = Лев(S, СтрДлина(S) - 4) + "9";
        ИначеЕсли (
Врем = "ОВНА") ИЛИ (Врем = "ЕВНА") Тогда
           
S = Лев(S, СтрДлина(S) - 4) + "8";
        ИначеЕсли (
Врем = "ОВИЧ") ИЛИ (Врем = "ЕВИЧ") Тогда
           
S = Лев(S, СтрДлина(S) - 4) + "7";
        Иначе
           
Врем = Прав(S, 3);
            Если (
Врем = "ОВА") ИЛИ (Врем = "ЕВА") Тогда
               
S = Лев(S, СтрДлина(S) - 3) + "9";
            ИначеЕсли
Врем = "ИНА" Тогда
               
S = Лев(S, СтрДлина(S) - 3) + "1";
            ИначеЕсли (
Врем = "ИЕВ") ИЛИ (Врем = "ЕЕВ") Тогда
               
S = Лев(S, СтрДлина(S) - 3) + "4";
            ИначеЕсли
Врем = "НКО" Тогда
               
S = Лев(S, СтрДлина(S) - 3) + "3";
            Иначе
               
Врем = Прав(S, 2);
                Если (
Врем = "ОВ") ИЛИ (Врем = "ЕВ") Тогда
                   
S = Лев(S, СтрДлина(S) - 2) + "4";
                ИначеЕсли
Врем = "АЯ" Тогда
                   
S = Лев(S, СтрДлина(S) - 2) + "6";
                ИначеЕсли (
Врем = "ИЙ") ИЛИ (Врем = "ЫЙ") Тогда
                   
S = Лев(S, СтрДлина(S) - 2) + "7";
                ИначеЕсли (
Врем = "ЫХ") ИЛИ (Врем = "ИХ") Тогда
                   
S = Лев(S, СтрДлина(S) - 2) + "5";
                ИначеЕсли (
Врем = "ИН") Тогда
                   
S = Лев(S, СтрДлина(S) - 2) + "8";
                ИначеЕсли (
Врем = "ИК") ИЛИ (Врем = "ЕК") Тогда
                   
S = Лев(S, СтрДлина(S) - 2) + "2";
                ИначеЕсли (
Врем = "УК") ИЛИ (Врем = "ЮК") Тогда
                   
S = Лев(S, СтрДлина(S) - 2) + "0";
                КонецЕсли;
            КонецЕсли;
        КонецЕсли;
    КонецЕсли;

   
//Оглушаем последний символ, если он - звонкий согласный:
   
B = Найти(cns1, Прав(S, 1));
    Если
B > 0 Тогда
       
S = Сред(S, СтрДлина(S)-1, 1);
       
S = S + Сред(cns2, B, 1);
    КонецЕсли;
   
old_c = " ";
   
//Основной цикл:
   
Для i = 1 По СтрДлина(S) Цикл
       
c = Сред(S, i, 1);
       
B = Найти(ch, c);
        Если
B > 0 Тогда //Если гласная
           
Если (old_c = "Й") ИЛИ (old_c = "И") Тогда
                Если (
c = "О") ИЛИ (c = "Е") Тогда //Буквосочетания с гласной
                   
old_c = "И";
                   
V = Сред(V, СтрДлина(V)-1, 1);
                   
V = V + old_c;
                Иначе
//Если не буквосочетания с гласной, а просто гласная
                   
Если c <> old_c Тогда
                       
V = V + Сред(ct, B, 1);
                    КонецЕсли;
                КонецЕсли;
            Иначе
//Если не буквосочетания с гласной, а просто гласная
               
Если c <> old_c Тогда
                       
V = V + Сред(ct, B, 1);
                КонецЕсли;
            КонецЕсли;
        Иначе
//Если согласная
           
Если c <> old_c Тогда //для «Аввакумов»
               
Если Найти(cns3, c) > 0 Тогда //Оглушение согласных
                   
B = Найти(cns1, old_c);
                КонецЕсли;
                Если
B > 0 Тогда
                   
old_c = Сред(cns2, B, 1);
                   
V = Сред(V, СтрДлина(V)-1, 1);
                   
V = V + old_c;
                КонецЕсли;
                Если
c <> old_c Тогда
                   
V = V + c; //для «Шмидт»
               
КонецЕсли;
            КонецЕсли;
        КонецЕсли;
       
old_c = c;
    КонецЦикла;
    Возврат
V;
КонецФункции
// ** MetaPhoneRu() algorithm **

См. также

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

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

21.05.2024    20124    dimanich70    81    

144

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

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

1 стартмани

18.03.2024    4091    3    John_d    11    

57

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

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

12.02.2024    18059    atdonya    24    

56

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

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

30.11.2023    5502    ke.92@mail.ru    16    

65

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

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

28.08.2023    14730    YA_418728146    7    

166

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

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

2 стартмани

22.08.2023    3580    56    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    18478    171    sapervodichka    112    

135
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. Арчибальд 2709 27.09.09 10:41 Сейчас в теме
2. JohnyDeath 302 28.09.09 09:57 Сейчас в теме
3. Поручик 4692 28.09.09 11:08 Сейчас в теме
(2) если вы про это http://infostart.ru/public/15765/, но я никогда не был любителем ВК.
4. JohnyDeath 302 28.09.09 11:32 Сейчас в теме
(3) я про ВК. по ссылке выше она используется. Также она используется не только мной. Все очень довольны. Если же нет желания использовать ВК, тогда ДА
5. Поручик 4692 28.09.09 11:38 Сейчас в теме
(4)
>>> Также она используется не только мной.
Знавал её ещё с клюшечных времён, так как тоже один или пару раз воспользовался, но потом по каким-то причинам отказался и забыл напрочь.
6. Sk0rp 119 21.10.09 11:36 Сейчас в теме
StrMatch использует алгоритмы MetaPhone
7. Поручик 4692 11.05.10 21:07 Сейчас в теме
К сожалению, ссылка http://www.kankowski.narod.ru/dev/metaphoneru.htm и сам сайт благополучно скончались. А жаль. Многие материалы там до сих пор были актуальными.
Есть мысль реанимировать статью «Как ваша фамилия», или Русский MetaPhone, сохранилась на диске. Стоит ли?
8. mikeA 1 13.05.10 14:11 Сейчас в теме
(7) Выкладывай, интересно будет прочитать.
Может быть есть ещё что-то на тему нечёткого поиска для ФИО?
9. Поручик 4692 13.05.10 14:16 Сейчас в теме
(8) Ну вот один отозвался. Хорошо, сегодня вывалю на своём сайте, да простит меня автор статьи.
11. Поручик 4692 14.05.10 00:39 Сейчас в теме
(8)
Ещё одна прикольная штука на тему нечёткого поиска. :D
Soundex на 1С: Предприятии

Сразу предупреждаю, тесты показали неожиданные результаты.
10. Поручик 4692 13.05.10 15:20 Сейчас в теме
12. mikeA 1 14.05.10 14:42 Сейчас в теме
Вот тогда до кучи функция для вычисления расстояния Левенштейна.
Взято отсюда.
Вроде бы больше похоже на правду - для Иванов и Иваноф метафон даёт разницу в два последних символа, расстояние Левенштейна единица.
Теперь осталось проверить как будет работать СписокПолнотекстовогоПоиска :)
Прикрепленные файлы:
levenshtein.txt
Поручик; +1 Ответить
13. Поручик 4692 14.05.10 17:47 Сейчас в теме
(12) Молодец!
О расстоянии Левенштейна думал раньше, руки не дошли.
Можно опубликую у себя? Только английские термины заменю на русские. Так гламурнее будет.

Кстати, ещё есть similar_text
http://ru2.php.net/manual/en/function.similar-text.php
Где бы найти описание алгоритма Оливера? Перетряхнул гугл, ничего внятного.
17. mikeA 1 18.05.10 14:52 Сейчас в теме
(13)
> Можно опубликую у себя?
Да без проблем.

Вот ещё материал: Sam's String Metrics - библиотека java, больше десятка подобных функций, с описанием.
19. Поручик 4692 18.05.10 16:54 Сейчас в теме
(17)
Кстати, твоё творчество здесь разместил.
14. Поручик 4692 14.05.10 18:18 Сейчас в теме
>>> Иванов и Иваноф, Васильев и Васильефф

Я бы сказал, логично что метафон в реализации Каньковского даёт различия, всё-таки окончание -оф, -еф для русских фамилий нехарактерно, скорее так напишут за бугром, причём с двумя -фф.
Хотя можно попробовать подправить алгоритм

[FIND]
Если (Врем = "ОВ") ИЛИ (Врем = "ЕВ") Тогда

[REPLACE WITH]

Если (Врем = "ОВ") ИЛИ (Врем = "ЕВ") ИЛИ (Врем = "ОФ")  ИЛИ (Врем = "ЕФ") Тогда
15. artbear 1563 15.05.10 07:19 Сейчас в теме
Данную задачу было бы интересно покрыть тестами для разных вариантов фамилий и звуковых сочетаний.
ИМХО это совсем несложно

Кстати, для имен, не фамилий, алгоритмы нормально работают?
16. Поручик 4692 15.05.10 16:00 Сейчас в теме
(15)
Были у меня подобные тесты в 2006 г, когда сливал данные из базы бухгалтерии и ИНЭК-Страховщика в одну на 1С Страхование или что-то в этом роде. Базы были примерно тысяч по 10 записей физлиц. Насколько помню, процент попадания для разных вариантов составил 90-95.
18. Поручик 4692 18.05.10 16:50 Сейчас в теме
Спасибо за ссылку, хотя цветовая гамма там аж глаза режет.
Это всё хорошо (библиотека), но вот формализованное или авторское описание алгоритма Оливера покоя не даёт :)))) Сырцы php смотрел, но в сях не особо силён.
20. KAV2 157 26.12.17 07:04 Сейчас в теме
По хорошему такое бы надо на уровне СУБД писать ((
Оставьте свое сообщение