Алгоритм работы с строкой ФИО

1. akeelow 12.05.24 11:39 Сейчас в теме
Была задача из строки "Фамилия Имя Отчество" сделать строку "Фамилия И.О.".

Я сделал так:

ФИО = "Куравлев Алексей Владимирович";

// Требуется сформировать следующее сообщение: "Куравлев Алексей Владимирович = Куравлев А.В."

Фамилия	= Сред(ФИО, 0, СтрНайти(ФИО, " ",,,1) - 1);

Имя = Сред(ФИО, СтрНайти(ФИО, " ",,,1) + 1, СтрНайти(ФИО, " ",,,2) - СтрНайти(ФИО, " ",,,1) - 1); 

Отчество = Сред(ФИО, СтрНайти(ФИО, " ",,,2) + 1, СтрДлина(ФИО) - СтрНайти(ФИО, " ",,,2));


Сообщить(ФИО + " = " + Фамилия + " " + Лев(Имя, 1) + "." + Лев(Отчество, 1) + ".");
Показать


Выглядит ужасно :) К сожалению более правильного решения придумать не смог, и подглядеть негде.

Покажите как бы решили данную задачу?
Прикрепленные файлы:
По теме из базы знаний
Ответы
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
2. spacecraft 12.05.24 11:46 Сейчас в теме
(1)
Покажите как бы решили данную задачу?

использовали бы типовые функции.

Из ЗУП:
Функция ЧастиИмени(ФамилияИмяОтчество) Экспорт
	
	Результат = Новый Структура("Фамилия,Имя,Отчество");
	
	ЧастиИмени = СтрРазделить(ФамилияИмяОтчество, " ", Ложь); 
	
	КоличествоДополнений = 0;
	
	Если ЧастиИмени.Количество() >= 1 Тогда
		Результат.Фамилия = ЧастиИмени[0];
	КонецЕсли;
	
	Если ЧастиИмени.Количество() >= 2 Тогда
		ПервыеЧастиИмени = Новый Массив;
		ПервыеЧастиИмени.Добавить(НСтр("ru = 'Абдул'"));
		ПервыеЧастиИмени.Добавить(НСтр("ru = 'Абу'"));
		
		Результат.Имя = ЧастиИмени[1];
		Если ПервыеЧастиИмени.Найти(ТРег(ЧастиИмени[1])) <> Неопределено 
			И ЧастиИмени.Количество() >= 3 Тогда
			КоличествоДополнений = КоличествоДополнений + 1;
			Результат.Имя = Результат.Имя + " " + ЧастиИмени[2];
		КонецЕсли;
	КонецЕсли;
	
	Если ЧастиИмени.Количество() >= 3 + КоличествоДополнений Тогда
		Результат.Отчество = ЧастиИмени[2 + КоличествоДополнений];
	КонецЕсли;
	
	Если ЧастиИмени.Количество() > 3 + КоличествоДополнений Тогда
		ДополнительныеЧастиОтчества = Новый Массив;
		ДополнительныеЧастиОтчества.Добавить(НСтр("ru = 'оглы'"));
		ДополнительныеЧастиОтчества.Добавить(НСтр("ru = 'улы'"));
		ДополнительныеЧастиОтчества.Добавить(НСтр("ru = 'уулу'"));
		ДополнительныеЧастиОтчества.Добавить(НСтр("ru = 'кызы'"));
		ДополнительныеЧастиОтчества.Добавить(НСтр("ru = 'гызы'"));
		ДополнительныеЧастиОтчества.Добавить(НСтр("ru = 'угли'"));
		
		Если ДополнительныеЧастиОтчества.Найти(НРег(ЧастиИмени[3 + КоличествоДополнений])) <> Неопределено Тогда
			Результат.Отчество = Результат.Отчество + " " + ЧастиИмени[3 + КоличествоДополнений];
		КонецЕсли;
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

// Формирует краткое представление из полного имени физического лица.
//
// Параметры:
//  ФамилияИмяОтчество - Строка - полное имя в виде "Фамилия Имя Отчество";
//                     - Структура:
//                        * Фамилия  - Строка - фамилия;
//                        * Имя      - Строка - имя;
//                        * Отчество - Строка - отчество.
//
// Возвращаемое значение:
//  Строка - фамилия и инициалы. Например, "Пупкин В. И.".
//
// Пример:
//  Результат = ФизическиеЛицаКлиентСервер.ФамилияИнициалы("Пупкин Василий Иванович"); 
//  - возвращает "Пупкин В. И.".
//
Функция ФамилияИнициалы(Знач ФамилияИмяОтчество) Экспорт
	
	Если ТипЗнч(ФамилияИмяОтчество) = Тип("Строка") Тогда
		ФамилияИмяОтчество = ЧастиИмени(ФамилияИмяОтчество);
	КонецЕсли;
	
	Фамилия = ФамилияИмяОтчество.Фамилия;
	Имя = ФамилияИмяОтчество.Имя;
	Отчество = ФамилияИмяОтчество.Отчество;
	
	Если ПустаяСтрока(Имя) Тогда
		Возврат Фамилия;
	КонецЕсли;
	
	Если ПустаяСтрока(Отчество) Тогда
		Возврат СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку("%1 %2.", Фамилия, Лев(Имя, 1));
	КонецЕсли;
	
	Возврат СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку("%1 %2. %3.", Фамилия, Лев(Имя, 1), Лев(Отчество, 1));
	
КонецФункции
Показать
5. akeelow 12.05.24 15:12 Сейчас в теме
3. starjevschik 12.05.24 13:44 Сейчас в теме
Да красиво выглядит. Форматирование супер, в тексте решения много воздуха, света, просторное размещение ключевых слов добавляет ощущение свободы и легкости кода. Запятых много по нынешней моде, тоже плюс. Все нужные комментарии не забыты.
Хоть прям сейчас на выставку достижений программеров 1с. Непонятно, что ужасного.

(1)
Покажите как бы решили данную задачу?

я бы к преподу пошел, пусть отрабатывает свою зарплату. Иначе зачем они вообще нужны?
6. akeelow 12.05.24 15:14 Сейчас в теме
(3) Непонятно что ужасного? Оно не читаемо же, через неделю не вспомнишь как оно работает
4. user1880116 12.05.24 13:45 Сейчас в теме
(1)
Покажите как бы решили данную задачу?
А на какую зарплату ты нас собеседуешь?
7. akeelow 12.05.24 15:15 Сейчас в теме
(4) На весь диапазон. Предложи решение, а там видно будет :)
8. akeelow 12.05.24 15:18 Сейчас в теме
Улучшил как мог)
ФИО = "Куравлев Алексей Владимирович";

ПервыйПробел = СтрНайти(ФИО, " ",,,1);
ВторойПробел = СтрНайти(ФИО, " ",,,2);

Фамилия  = Сред(ФИО, 0, ПервыйПробел - 1);
Имя      = Сред(ФИО,    ПервыйПробел + 1, 1); 
Отчество = Сред(ФИО,    ВторойПробел + 1, 1);
                                                         
Сообщить(СтрШаблон("%1 = %2 %3.%4.", ФИО, Фамилия, Имя, Отчество));
Показать
9. Vinzor 107 12.05.24 19:54 Сейчас в теме
(8) Попробуй так (писал по памяти, чего и вам желаю)
ФИО = "Куравлев Алексей Владимирович";
Массик = СтрРазделить(ФИО,Символ(32), ложь);
Фамилия = СокрЛП(Массик[0]) + " ";
Имя = Лев(СокрЛП(Массик[1]), 1) + ".";
Отчество = Лев(СокрЛП(Массик[2]), 1) + ".";
Ответ = ФИО  + " = " + Фамилия + Имя + Отчество;
Сообщить(Ответ);

Ну и через "шаблон" тоже можно
ФИО = "Куравлев Алексей Владимирович";
Массик = СтрРазделить(ФИО,Символ(32), ложь);
Фамилия = СокрЛП(Массик[0]);
Имя = Лев(СокрЛП(Массик[1]), 1);
Отчество = Лев(СокрЛП(Массик[2]), 1);
Ответ = СтрШаблон("%1 = %2 %3.%4.", ФИО, Фамилия, Имя, Отчество);
Сообщить(Ответ);
10. akeelow 12.05.24 20:10 Сейчас в теме
(9) Красиво! Еще массивы не изучал, но выглядят вроде логично, тоже надо с ними попробовать.
11. user1880116 12.05.24 21:13 Сейчас в теме
12. Vinzor 107 13.05.24 08:56 Сейчас в теме
(11) Отсечь случайные паразитарные пробелы слева / справа в частях фразы
14. user1880116 15.05.24 16:13 Сейчас в теме
(12)
паразитарные пробелы
Откуда они там возьмутся при твоём предложеном алгоритме?
15. Vinzor 107 15.05.24 16:16 Сейчас в теме
(14)
А если во входящей строке будет много пробелов между словами?

Поймите, не надо ограничиваться текущим заданием.
Лучше делать "на автомате" так, чтобы предотвратить те ошибки, которые могут быть в реальной жизни.
Тем более что вписать "СокрЛП" всего ровно на 5 сек дольше по времени, чем не вписать.
16. akeelow 15.05.24 16:20 Сейчас в теме
(15)А если пробел будет в начале или после фамилии будет два пробела, не получится так, что элементов массива будет больше трёх?
17. Vinzor 107 15.05.24 16:21 Сейчас в теме
(16)
Если в начале или конце фразы могут быть пробелы, то для этого надо сразу сделать так
ФИО = "Куравлев Алексей Владимирович";
ФИО = СокрпЛП(ФИО);

Если есть опасение, что разобьёт на более чем 3 элемента массива (из-за пробелов), тогда массив надо обходить в цикле и

Первый = истина;
Для каждого стр Из МассивСтрок Цикл
      Если НЕ ПустаяСтрока(СокрЛП(стр)) Тогда   // игнорируем по сути пустые элементы массива 
           Если Первый тогда   // первый элемент, он же фамилия
                ФИО = ФИО + СокрЛП(Стр) + " ";   // добавили фамилию + пробел
                Первый = ложь;
           Иначе
                 ФИО = ФИО + Лев(СокрЛП(стр),1) + ".";   // добавили аббревиатуру имени или отчества
           КонецЕсли;
     КонецЕсли;
КонецЦикла
Показать
18. user1880116 15.05.24 16:28 Сейчас в теме
(15)
А если во входящей строке будет много пробелов между словами?
То они уничтожатся после выполнения СтрРазделить.
Лучше делать "на автомате" так, чтобы предотвратить те ошибки, которые могут быть в реальной жизни.
Ну, ты же не предусмотрел вариант, когда твой Массик[2] развалится по выходу индекса за границу массива. А всё туда же...
19. Vinzor 107 15.05.24 16:33 Сейчас в теме
(18) Не дерзи. Я для ЗУПа столько контролей и доработок написал (часть из них выложил в моих публикациях), что мне данное задание как возня малыша в песочнице.
20. пользователь 15.05.24 19:33
Сообщение было скрыто модератором.
...
21. SlavaKron 16.05.24 08:16 Сейчас в теме
(18)
Массик[2] развалится по выходу индекса за границу массива
Это избыточная проверка, т.к. функция должна выполнять только одно действие, только то, что от нее просят. Проверка на количество элементов относится к нормализации и подготовке данных, а это уже другая задача. Повсеместное использование "Знач" и СокрЛП из той же серии. Выполнение таких проверок может накапливаться как снежный ком при глубокой вложенности вызова. Пример абсурдных проверок:
Функция Деление(Знач Число1, Знач Число2)
	
	ТипЧисло = Новый ОписаниеТипов("Число");
	
	Если ТипЗнч(Число2) <> Тип("Число") Тогда
		Число2 = ТипЧисло.ПривестиЗначение(Число2);
	КонецЕсли;
	
	Если Число2 = 0 Тогда
		Возврат Неопределено
	КонецЕсли;
	
	Если ТипЗнч(Число1) <> Тип("Число") Тогда
		Число1 = ТипЧисло.ПривестиЗначение(Число1);
	КонецЕсли;
	
	Попытка
		Результат = Число1 / Число2
	Исключение
		Возврат Неопределено
	КонецПопытки;
	
	Возврат Результат
	
КонецФункции
Показать
Вместо простого
Функция Деление(Число1, Число2)
	Возврат Число1 / Число2
КонецФункции
22. user1880116 16.05.24 08:21 Сейчас в теме
(21)
Проверка на количество элементов относится к нормализации и подготовке данных, а это уже другая задача
Вон там в (2) в куске кода из зупа разные оглыкызы обрабатываются. Это еще нормализация или уже обработка? Теоретики...
23. SlavaKron 16.05.24 08:28 Сейчас в теме
(22) Постановка задачи в (1), обработка "оглы" или полного имени из двух слов - это всё преждевременная оптимизация перестраховка.
24. Vinzor 107 16.05.24 10:11 Сейчас в теме
(22) Нормально в ЗУПе для этого берется запись из РС "ФИО физлиц", где фамилия, имя, отчество являются отдельными ресурсами регистра.
И я бы сделал в виде запроса,
ВЫБРАТЬ
	ДАТАВРЕМЯ(1, 1, 1) КАК Период,
	ФизическиеЛица.Ссылка КАК ФизическоеЛицо
ПОМЕСТИТЬ ВТФизическиеЛицаПериоды
ИЗ
	Справочник.ФизическиеЛица КАК ФизическиеЛица
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
	ДАТАВРЕМЯ(1, 1, 1) КАК Период,
	ЗНАЧЕНИЕ(Справочник.ФизическиеЛица.ПустаяСсылка) КАК ФизическоеЛицо,
	"" КАК ФамилияИО
ПОМЕСТИТЬ Представления_КадровыеДанныеФизическихЛиц
ИЗ
	ВТФизическиеЛицаПериоды КАК ФизическиеЛицаПериоды
Показать

Который далее крутанул бы через этот метод
ЗарплатаКадрыОбщиеНаборыДанных.ЗаменитьЗапросыКПредставлениямВиртуальныхТаблиц(Текст);

и далее вложил бы в "Запрос" и исполнил, получил выборку
13. Vlan 36 13.05.24 11:04 Сейчас в теме
Правильно и красиво - через массив. Но если задание их использовать запрещает, то можно перебрать строку посимвольно. Примерно так:

	ФИО=СтрЗаменить(ФИО,"  "," "); //На всякий случай убираем два пробела
	Начало=Истина;
	Для сч=1 По СтрДлина(ФИО) Цикл
		Симв=Сред(ФИО,сч,1);
		Если Симв=" " Тогда
			Если Начало Тогда
				Начало=Ложь;
				Фамилия=Лев(ФИО,сч);
				Имя=Сред(ФИО,сч+1,1)+".";
			Иначе
				Отчество=Сред(ФИО,сч+1,1)+".";
			КонецЕсли;
		КонецЕсли;
	КонецЦикла;
	Возврат Фамилия+Имя+Отчество;

Показать
Оставьте свое сообщение

Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот