Алгоритмы и функции для обработки текстовых данных
- ttm
- профи
- Сообщения: 140
- Зарегистрирован: 09 июн 2022, 12:24
- Благодарил (а): 435 раз
- Поблагодарили: 218 раз
Алгоритмы и функции для обработки текстовых данных
Предлагаю сюда накидывать все, что облегчает обработку и чистку данных.
Последний раз редактировалось ttm 09 апр 2025, 13:48, всего редактировалось 1 раз.
- ttm
- профи
- Сообщения: 140
- Зарегистрирован: 09 июн 2022, 12:24
- Благодарил (а): 435 раз
- Поблагодарили: 218 раз
ФИО из транслита в русский
Давно хотел, но все руки не доходили.
Алго не идеально, не учитывает все-все-все нюансы, но его можно дополнять и улучшать, что приветствуется.
Потестить можно тут: [External Link Removed for Guests]
На входе получает: Bulochkina Ksenia
На выходе: Булочкина Ксения
Алго не идеально, не учитывает все-все-все нюансы, но его можно дополнять и улучшать, что приветствуется.
translitToRussian.js
Код: [Local Link Removed for Guests]
function translitToRussian(text) {
// Проверка: если строка пустая или состоит только из пробелов, возвращаем её без изменений
if (!text.trim() || /^[а-яА-ЯёЁ\s]+$/.test(text)) {
return text;
}
const exceptions = {
// Примеры фамилий с польскими и чешскими окончаниями
'gelajec': 'гелажец',
'skoczylas': 'скочылас',
'kachajec': 'кажец',
'jeremic': 'жеремич',
'kaczmarczyk': 'кацмарчик',
'szczerbak': 'щербак',
'poznajec': 'позняц',
'szielezny': 'сзелезный',
'kowalczyk': 'ковальчик',
'czyzewski': 'чыжевский',
'ziegler': 'циглер',
'ziech': 'цих',
'czycz': 'чиц',
'wieczorek': 'вецерек',
'leszczynski': 'лешчинский',
'mikolajczak': 'миколайчак',
'wojcik': 'войцик',
'chruszcz': 'хрусч',
'pietrzak': 'петржак',
'wroblewski': 'врублевский',
'cieslak': 'чешлак',
// Общие имена
'daria': 'дарья',
'igor': 'игорь',
'alex': 'александр',
'alexander': 'александр',
'zavgorodniaia': 'завгородняя',
'siniaev': 'синяев',
'ganiaev': 'ганяев',
'katiaev': 'катяев',
'toliaev': 'толяев',
'daniaev': 'даняев',
'liapin': 'ляпин',
'viakhirev': 'вяхирев',
'tiaglov': 'тяглов',
'riabov': 'рябов',
'pianiov': 'пьяниов',
'batiaev': 'батяев',
'saniaev': 'саняев',
'faniaev': 'фаняев',
'natalia': 'наталья',
'arnold': 'арнольд',
'ksenia': 'ксения',
'kusowa': 'кусова'
};
const endings = [
[/yev$/, 'ьев'],
[/ii$/, 'ий'],
[/ei$/, 'ей'],
[/iy$/, 'ий'],
[/iya$/, 'ия'],
[/ckaia$/, 'цкая'],
[/skaia$/, 'ская'],
[/kaia$/, 'кая'],
[/tskaia$/, 'цкая'],
[/zhkaia$/, 'жкая'],
[/shkaia$/, 'шкая'],
[/chkaia$/, 'чкая'],
[/([^кцсжчшщ])ia$/, '$1я'],
[/ey$/, 'ей'],
[/ai$/, 'ай'],
[/oi$/, 'ой'],
[/ui$/, 'уй'],
[/ovaia$/, 'овая'],
[/ova$/, 'ова'],
[/evna$/, 'евна'],
[/ovna$/, 'овна'],
[/ich$/, 'ич'],
[/ina$/, 'ина'],
[/sky$/, 'ский'],
[/skaya$/, 'ская'],
[/ny$/, 'ний'],
[/y$/, 'й']
];
const rules = [
['shch', 'щ'],
['kh', 'х'],
['tck', 'ц'],
['ck', 'ц'],
['yo', 'ё'],
['zh', 'ж'],
['ch', 'ч'],
['sh', 'ш'],
['yu', 'ю'],
['ya', 'я'],
['ts', 'ц'],
['ye', 'е'],
['x', 'кс'],
['e', 'е'],
['a', 'а'],
['b', 'б'],
['v', 'в'],
['g', 'г'],
['d', 'д'],
['z', 'з'],
['i', 'и'],
['j', 'й'],
['k', 'к'],
['l', 'л'],
['m', 'м'],
['n', 'н'],
['o', 'о'],
['p', 'п'],
['r', 'р'],
['s', 'с'],
['t', 'т'],
['u', 'у'],
['f', 'ф'],
['h', 'х'],
['c', 'к']
];
const replaceAllSafe = (str, search, replace) => {
return str.replace(
new RegExp(search.replace(/([.*+?^=!:${}()|[\]/\\])/g, '\\$1'), 'g'),
replace
);
};
const capitalize = (word) =>
word.charAt(0).toUpperCase() + word.slice(1);
return text.split(' ').map((word) => {
let lower = word.toLowerCase();
// 1. Очистка ошибочных окончаний
lower = lower
.replace(/iaia$/, 'ia')
.replace(/iiia$/, 'ia')
.replace(/iia$/, 'ia')
.replace(/iiy$/, 'iy');
// 2. Исключения
if (exceptions[lower]) {
return capitalize(exceptions[lower]);
}
// 3. Обработка tc / tce / vtce / iav
lower = lower
.replace(/vtce/g, 'вце')
.replace(/tce/g, 'це')
.replace(/tc/g, 'ц')
.replace(/iav/g, 'яв');
// 4. Спец. замены в середине слова
lower = lower
.replace(/([бвгджзклмнпрстфхцчшщ])ia([еёийоуаэыюя])/g, '$1я$2')
.replace(/([бвгджзклмнпрстфхцчшщ])io/g, '$1ё')
.replace(/([бвгджзклмнпрстфхцчшщ])ie/g, '$1ье')
.replace(/([бвгджзклмнпрстфхцчшщ])ei/g, '$1ей');
// 5. Заменяем "u" на "ю" в имени
lower = lower.replace(/u([аеёиоуыэюя])/g, 'ю$1');
// 6. Правило для "oi" в середине, если это не часть имени
lower = lower.replace(/oi/g, 'ой');
// 7. Окончания
for (const [regex, replacement] of endings) {
if (regex.test(lower)) {
lower = lower.replace(regex, replacement);
break;
}
}
// 8. Общие правила
for (const [lat, rus] of rules.sort((a, b) => b[0].length - a[0].length)) {
lower = replaceAllSafe(lower, lat, rus);
}
return capitalize(lower);
}).join(' ');
}
На входе получает: Bulochkina Ksenia
На выходе: Булочкина Ксения
- ttm
- профи
- Сообщения: 140
- Зарегистрирован: 09 июн 2022, 12:24
- Благодарил (а): 435 раз
- Поблагодарили: 218 раз
Заменяет латинские буквы в русском тексте на русские
Заменяет латинские буквы в русском тексте на русские, если латинских меньше половины от общего числа.
fixMixedAlphabet.js
Код: [Local Link Removed for Guests]
function fixMixedAlphabet(text) {
const latinToCyrillicMap = {
'A': 'А', 'B': 'В', 'C': 'С', 'E': 'Е', 'H': 'Н',
'K': 'К', 'M': 'М', 'O': 'О', 'P': 'Р', 'T': 'Т',
'X': 'Х', 'Y': 'У',
'a': 'а', 'c': 'с', 'e': 'е', 'o': 'о', 'p': 'р',
'x': 'х', 'y': 'у',
};
const latinLetters = Object.keys(latinToCyrillicMap);
let totalLetterCount = 0;
let latinLetterCount = 0;
for (let char of text) {
if (/[a-zA-Zа-яА-ЯёЁ]/.test(char)) {
totalLetterCount++;
if (latinLetters.includes(char)) {
latinLetterCount++;
}
}
}
const latinRatio = latinLetterCount / (totalLetterCount || 1); // делим на 1 чтобы избежать деления на 0
if (latinRatio > 0.5) {
// Похоже, что текст в основном латинский — не трогаем
return text;
}
// Заменяем латинские буквы на похожие русские
return text.split('').map(char => latinToCyrillicMap[char] || char).join('');
}
- Burg0mister
- профи
- Сообщения: 326
- Зарегистрирован: 19 июл 2022, 17:07
- Благодарил (а): 1794 раза
- Поблагодарили: 697 раз
Re: ФИО из транслита в русский
Приветствую![Local Link Removed for Guests] писал(а): [Local Link Removed for Guests]09 апр 2025, 13:47 Давно хотел, но все руки не доходили.
Алго не идеально, не учитывает все-все-все нюансы, но его можно дополнять и улучшать, что приветствуется.
Потестить можно тут: [External Link Removed for Guests]translitToRussian.js
Код: [Local Link Removed for Guests]
function translitToRussian(text) { // Проверка: если строка пустая или состоит только из пробелов, возвращаем её без изменений if (!text.trim() || /^[а-яА-ЯёЁ\s]+$/.test(text)) { return text; } const exceptions = { // Примеры фамилий с польскими и чешскими окончаниями 'gelajec': 'гелажец', 'skoczylas': 'скочылас', 'kachajec': 'кажец', 'jeremic': 'жеремич', 'kaczmarczyk': 'кацмарчик', 'szczerbak': 'щербак', 'poznajec': 'позняц', 'szielezny': 'сзелезный', 'kowalczyk': 'ковальчик', 'czyzewski': 'чыжевский', 'ziegler': 'циглер', 'ziech': 'цих', 'czycz': 'чиц', 'wieczorek': 'вецерек', 'leszczynski': 'лешчинский', 'mikolajczak': 'миколайчак', 'wojcik': 'войцик', 'chruszcz': 'хрусч', 'pietrzak': 'петржак', 'wroblewski': 'врублевский', 'cieslak': 'чешлак', // Общие имена 'daria': 'дарья', 'igor': 'игорь', 'alex': 'александр', 'alexander': 'александр', 'zavgorodniaia': 'завгородняя', 'siniaev': 'синяев', 'ganiaev': 'ганяев', 'katiaev': 'катяев', 'toliaev': 'толяев', 'daniaev': 'даняев', 'liapin': 'ляпин', 'viakhirev': 'вяхирев', 'tiaglov': 'тяглов', 'riabov': 'рябов', 'pianiov': 'пьяниов', 'batiaev': 'батяев', 'saniaev': 'саняев', 'faniaev': 'фаняев', 'natalia': 'наталья', 'arnold': 'арнольд', 'ksenia': 'ксения', 'kusowa': 'кусова' }; const endings = [ [/yev$/, 'ьев'], [/ii$/, 'ий'], [/ei$/, 'ей'], [/iy$/, 'ий'], [/iya$/, 'ия'], [/ckaia$/, 'цкая'], [/skaia$/, 'ская'], [/kaia$/, 'кая'], [/tskaia$/, 'цкая'], [/zhkaia$/, 'жкая'], [/shkaia$/, 'шкая'], [/chkaia$/, 'чкая'], [/([^кцсжчшщ])ia$/, '$1я'], [/ey$/, 'ей'], [/ai$/, 'ай'], [/oi$/, 'ой'], [/ui$/, 'уй'], [/ovaia$/, 'овая'], [/ova$/, 'ова'], [/evna$/, 'евна'], [/ovna$/, 'овна'], [/ich$/, 'ич'], [/ina$/, 'ина'], [/sky$/, 'ский'], [/skaya$/, 'ская'], [/ny$/, 'ний'], [/y$/, 'й'] ]; const rules = [ ['shch', 'щ'], ['kh', 'х'], ['tck', 'ц'], ['ck', 'ц'], ['yo', 'ё'], ['zh', 'ж'], ['ch', 'ч'], ['sh', 'ш'], ['yu', 'ю'], ['ya', 'я'], ['ts', 'ц'], ['ye', 'е'], ['x', 'кс'], ['e', 'е'], ['a', 'а'], ['b', 'б'], ['v', 'в'], ['g', 'г'], ['d', 'д'], ['z', 'з'], ['i', 'и'], ['j', 'й'], ['k', 'к'], ['l', 'л'], ['m', 'м'], ['n', 'н'], ['o', 'о'], ['p', 'п'], ['r', 'р'], ['s', 'с'], ['t', 'т'], ['u', 'у'], ['f', 'ф'], ['h', 'х'], ['c', 'к'] ]; const replaceAllSafe = (str, search, replace) => { return str.replace( new RegExp(search.replace(/([.*+?^=!:${}()|[\]/\\])/g, '\\$1'), 'g'), replace ); }; const capitalize = (word) => word.charAt(0).toUpperCase() + word.slice(1); return text.split(' ').map((word) => { let lower = word.toLowerCase(); // 1. Очистка ошибочных окончаний lower = lower .replace(/iaia$/, 'ia') .replace(/iiia$/, 'ia') .replace(/iia$/, 'ia') .replace(/iiy$/, 'iy'); // 2. Исключения if (exceptions[lower]) { return capitalize(exceptions[lower]); } // 3. Обработка tc / tce / vtce / iav lower = lower .replace(/vtce/g, 'вце') .replace(/tce/g, 'це') .replace(/tc/g, 'ц') .replace(/iav/g, 'яв'); // 4. Спец. замены в середине слова lower = lower .replace(/([бвгджзклмнпрстфхцчшщ])ia([еёийоуаэыюя])/g, '$1я$2') .replace(/([бвгджзклмнпрстфхцчшщ])io/g, '$1ё') .replace(/([бвгджзклмнпрстфхцчшщ])ie/g, '$1ье') .replace(/([бвгджзклмнпрстфхцчшщ])ei/g, '$1ей'); // 5. Заменяем "u" на "ю" в имени lower = lower.replace(/u([аеёиоуыэюя])/g, 'ю$1'); // 6. Правило для "oi" в середине, если это не часть имени lower = lower.replace(/oi/g, 'ой'); // 7. Окончания for (const [regex, replacement] of endings) { if (regex.test(lower)) { lower = lower.replace(regex, replacement); break; } } // 8. Общие правила for (const [lat, rus] of rules.sort((a, b) => b[0].length - a[0].length)) { lower = replaceAllSafe(lower, lat, rus); } return capitalize(lower); }).join(' '); }
На входе получает: Bulochkina Ksenia
На выходе: Булочкина Ксения
Отличная идея, тоже об этом задумывался, но потом в профильном разделе уже кто-то создал похожую тему с советами по обработке. Но не в этом суть.
Хочу предложить небольшое усовершенствование для работы по транслиту, потому что в некоторых базах есть хитрость, которая не все строчки позволит исправить. Знаете подставу с перемешиванием латиницы и кириллицы в автомобильных номерах, VIN и ФИО?
Это когда
иАлександр Иванов
Читаются одинаково, но на самом деле часть букв написана латиницей, а часть кириллицей.Aлeкcaндр Ивaнoв
Перед конвертированием латиницы в кирилицу стоит провести проверку и исправление в рамках выделенного столбца и заменить кириллические символы на латинские, а уже потом конвертировать все полностью в кириллицу.
Спойлер
Если на раздачи ставлю личный пароль - делюсь им безвозмездно, так же он есть и у администрации! Приму в дар БД с контактами, ФИО, адресами по СНГ/РФ. Интересуют: Современные ГИБДД, банки, блэклисты банков, телефоны, спецучет и т. п.