Функция Русский 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 **

Вступайте в нашу телеграмм-группу Инфостарт

См. также

Загрузка и выгрузка в Excel Универсальные функции Программист 1С:Предприятие 8 Россия Бесплатно (free)

Описанный ниже подход позволяет в три шага заполнять формулы в Excel файлы, вне зависимости от ОС сервера (MS Windows Server или Linux). Подход подразумевает отказ от работы с COM-объектом в пользу работы через "объектную модель документа" (DOM).

30.10.2025    3193    Abysswalker    7    

43

Универсальные функции Работа с интерфейсом Программист 1С:Предприятие 8 Бесплатно (free)

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

14.05.2025    5988    DeerCven    15    

57

Универсальные функции Программист 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)

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

21.05.2024    47741    dimanich70    83    

168

Универсальные функции Программист 1С:Предприятие 8 1C:Бухгалтерия Абонемент ($m)

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

1 стартмани

18.03.2024    7182    6    John_d    13    

59

Универсальные функции Программист Стажер 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)

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

12.02.2024    59465    atdonya    31    

69

Универсальные функции Программист 1С:Предприятие 8 Бесплатно (free)

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

30.11.2023    8945    ke.92@mail.ru    17    

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

Сразу предупреждаю, тесты показали неожиданные результаты.
10. Поручик 4599 13.05.10 15:20 Сейчас в теме
12. mikeA 1 14.05.10 14:42 Сейчас в теме
Вот тогда до кучи функция для вычисления расстояния Левенштейна.
Взято отсюда.
Вроде бы больше похоже на правду - для Иванов и Иваноф метафон даёт разницу в два последних символа, расстояние Левенштейна единица.
Теперь осталось проверить как будет работать СписокПолнотекстовогоПоиска :)
Прикрепленные файлы:
levenshtein.txt
Поручик; +1 Ответить
13. Поручик 4599 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. Поручик 4599 18.05.10 16:54 Сейчас в теме
(17)
Кстати, твоё творчество здесь разместил.
14. Поручик 4599 14.05.10 18:18 Сейчас в теме
>>> Иванов и Иваноф, Васильев и Васильефф

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

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

[REPLACE WITH]

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

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