Разбивка строки ФИО на Фамилию Имя Отчество
0 (0)
- Разбивка строки ФИО на Фамилию Имя Отчество ( Andrew01 24.04.2019 10:19 )5(1)Здравствуйте.
собственно subject
StrSplit и SstrSplit2 не подходят.
Как можно любую строку, например "Иванов Иван Иванович" разбить на отдельные сегменты?
Отдельно Иванов, Иван, Иванович.
Может быть любая фамилия, необходима функция чтобы вытаскивала отдельно ФИО.
>> Ответить- поковырялся, но вариант не точный ( Andrew01 24.04.2019 12:15 )0(0)
var fio:string;
fio = "ОЛОГОТОЧЕРЕПАПИНСКОВСКИЙ АБДУМАЛЬДИН АБДУРАХМАНОВИЧ";
macro SplitFio(str:string,f:integer)
var fam,name,sur,tmp1,tmp2 : string;
fam = strsplit2(str, index(str, " "), true);
tmp1 = trim(substr(str, strlen(fam(0))));
name = strsplit2(tmp1, index(tmp1, " "), true);
tmp2 = fam(0) + " " + name(0);
sur = SubStr(str,strlen(tmp2));
if((f == 0)or(f == NULL))
return fam(0);
elif (f == 1)
return name(0);
elif (f == 2)
return sur;
else
return str;
end;
end;
println("Фамилия: " + SplitFio(fio,0));
println("Имя: " + SplitFio(fio,1));
println("Отчество: " + SplitFio(fio,2));
Но если человек без отчества, то начинаются проблемы.
>> Ответить- у меня три варианта разбиения строки в массив ( KaMPiLeR 25.04.2019 17:01 )5(1)
macro evd_split(ch, s, a, l)
//тут идея такая - меняем символ разделителя на \n и используем стандартную функцию разделения
var i;
if(valtype(l)==V_UNDEF)
l=255;
end;
asize(a,0);
s=strsubst(s,ch,"\n");
strsplit(s,a,l);
i=0;
while(i<l)//asize(a)
//a[i];
if(valtype(a[i])==V_UNDEF) a[i]=""; end;
i=i+1;
end;
setparm(2,a);
return(true);
end;
macro evd_split_(ch, s, l)
//а тут уже по маске разделителей
var w=tarray, i, k, p;
s=s+substr(ch,1,1);
i=1;
k=0;
p=1;
while(i<=strlen(s))
if(index(ch,substr(s,i,1))>0)
w(k)=substr(s,p,i-p);
w(k)=trim(w(k));
if(w(k)!="") k=k+1; end;
p=i+1;
end;
i=i+1;
end;
return(w);
end;
macro evd_split_char(s, a, l)
var i=1;
asize(a,0);
while(i<=l)//
a[i]=substr(s,i,1);
i=i+1;
end;
setparm(2,a);
return(true);
end;
>> Ответить
- у меня три варианта разбиения строки в массив ( KaMPiLeR 25.04.2019 17:01 )
- Универсальная разбивалка строк в массив ( Marik 25.04.2019 18:34 )0(0)
/** Возвращает массив строк, после разделения исходной строки 'str' по 'delim'. */
Macro StrSplitToArray(str : String, delim : String) : TArray
var result = TArray();
var dl = StrLen(delim);
var sl = StrLen(str);
if (dl == 0)
StrSplit(str, result, 1);
return result;
end;
var stPos = 1, i = 0, pos = Index(str, delim);
while ((pos > 0) and (stPos < sl))
result[i] = SubStr(str, stPos, pos - stPos);
stPos = pos + dl;
pos = Index(str, delim, stPos);
i = i + 1;
end;
if (stPos < sl)
result[i] = SubStr(str, stPos);
end;
return result;
End;
var fio = "Иванов Иван Иванович";
var res = StrSplitToArray(fio, " ");
println(res[0]);
println(res[1]);
println(res[2]);
>> Ответить - Вроде задача разбивки именно в массив не стояла... ( Крестьяников Андрей 25.04.2019 18:55 )0(0)
MACRO SplitFIO( fio, fam, nam, otch ) MACRO OneWord() VAR pos, ret; fio = Trim(fio); if( (pos=Index(fio," ")) <= 0 ) pos=StrLen(fio)+1; end; ret = SubStr(fio,1,pos-1); fio = SubStr(fio,pos+1); return ret; END; SetParm( 1, OneWord() ); SetParm( 2, OneWord() ); SetParm( 3, OneWord() ); END; VAR fam, nam, otch; SplitFIO( "Иванов Иван Иванович ", fam, nam, otch ); MsgBox( fam,",",nam,",",otch );
Функция нечувствительна к отсутствию отчества ( да и имени с фамилией )) ), количеству пробелов до, после и между частями ФИО.
>> Ответить- Благодарю всех, помогли. ( Andrew01 27.04.2019 16:21 )0(0)Not specified
>> Ответить
- Благодарю всех, помогли. ( Andrew01 27.04.2019 16:21 )
- Это достаточно трудная задача и в общем случае она не решается. ( tema 06.05.2019 00:31 )5(1)Not specified
>> Ответить - Разбивка на слова через регулярку ( Ulan 16.07.2019 14:52 )0(0)Как вариант:
import boostre;
macro splitStringBySpace(pString : String)
var resultArray = TArray();
var regexp = "([^ ]+)";
var errStr;
var machList = TArray();
boostre_match_2(regexp, pString, errStr, machList, "a");
var i = 0;
while (i < machList.size)
resultArray[i] = machList[i][0];
i = i + 1;
end;
return resultArray;
end;
macro printArray(pArray : TArray, pHeadLine : String)
PrintLn("***********************************************************");
PrintLn(pHeadLine : 60 : c);
PrintLn("-----------------------------------------------------------");
var i = 0;
while (i < pArray.size)
PrintLn(i + ": " + pArray[i]);
i = i + 1;
end;
PrintLn("***********************************************************");
end;
printArray(splitStringBySpace("Слово1 Слово2 Слово3 Слово4 Слово5 Слово6 Слово7"), "7 СЛОВ");
printArray(splitStringBySpace("Слово1 Слово2"), "2 СЛОВА");
printArray(splitStringBySpace(" "), "ПРОСТО ПРОБЕЛ");
printArray(splitStringBySpace(""), "ПУСТАЯ СТРОКА");
printArray(splitStringBySpace(null), "NULL-ЗНАЧЕНИЕ");
printArray(splitStringBySpace("Иванов Иван Иванович"), "ПОЛНОЕ ФИО");
printArray(splitStringBySpace("Иванов И. И."), "СОКРАЩЕННОЕ ФИО");
>> Ответить- интересненько, но ( tema 28.08.2019 23:46 )0(0)деление ФИО одной строй на фамилию имя и отчество не решается простой разбивкой на слова. одну мою знакомую зовут «Анна Светлана», дальше обычные фамилия и отчество. среди клиентов на дальнем востоке попадаются этническе корейцы. типа Ким это фамилия, «Чен Ын» это имя, отчества нет. есть «оглы» и «кызы» которые составлют отчество, но отделяются от основной части отчества пробелом. есть испанскицы этнические, у них всё сложно. фамилии перед которыми через пробел идёт де или фон. наверняка, есть ещё куча граблей, по которым я не хаживал. т.е. отличный алгорим должен опираться на словари имён и фамилий и уметь привлечь внимание человека, если случай стрёмный.
>> Ответить- Согласен, задача более сложная, чем разбивка строки на слова (+) ( григ 29.08.2019 08:30 )0(0)Есть самописная функция, которую я несколько раз правил. Да, она в частности юзает словарь имен-отчеств, который я регулярно пополняю. Двойные имена через "-" или пробел обрабатывает. Двойные отчества, фамилии через "-" - тоже. Всякие "Агаев Азиз Ага Мирзабек Оглы" - обрабатывает. Кажись даже прибалтов "Тускенис Роланд Альгирдас" обрабатывает. Корейское "Ким Чен Ын" неправильно разбирает, но возможно, если завести в словарь имена "Чен" и "Ын" - будет считать за двойное имя. Не было пока таких клиентов. В общем не все так просто.
>> Ответить- Корейцев по фамилии надо отлавливать (+) ( tema 29.08.2019 23:34 )0(0)У них три фамилии на всю страну.
оглы со строчной должно идти.
Доволнительно применение словарей и анализ суффиксов позволяет написать функцию getSex, правильнее, наверное, gender, но название поля в rs-ке наводит именно на такой вариант )
А ещё юрдеп любит запилить и утвердить форму с родительным падежом.
Да, в эту задачу можно погружаться на любую глубину.
>> Ответить- С "оглы" не совсем так (+) ( григ 30.08.2019 07:43 )5(1)- у них в паспортах есть и с маленькой буквы и с большой буквы, а еще есть через черточку. И кроме "оглы" есть другие словоформы. Я юзаю такую функцию:
//проверить наличие в отчестве тюркской части - вернуть ее, если есть
//P-исходное отчество, rod-вернуть род отчества, N-вернуть имя отца
//2015.08.25,LG,возврат имени отца, возврат вида отчества kind:1-тюрское,2-арабское
//- оглы (азерб. тур.)
//- угли (узб)
//- уулы (кирг.)
//- оол (тувынский)
//- оглу
macro hlx_TurkFather(P,rod,N,kind)
local var P1,ArP=TArray,ArR=TArray,ArP1=TArray,ArR1=TArray,i,len,ndx;
if(valtype(P)!=V_STRING) return P; end;
P=hl_Replace(trim(P)," "," "); //убираем двойные пробелы
P=strsubst(P," -","-"); P=strsubst(P,"- ","-"); //убираем пробелы вокруг дефисов
P1=strlwr(P); len=strlen(P1);
//тюрские - в конце отчества
ArP[ArP.Size]="оглы"; ArR[ArR.Size]=1;
ArP[ArP.Size]="оглу"; ArR[ArR.Size]=1;
ArP[ArP.Size]="угли"; ArR[ArR.Size]=1;
ArP[ArP.Size]="уулы"; ArR[ArR.Size]=1;
ArP[ArP.Size]="уулу"; ArR[ArR.Size]=1;
ArP[ArP.Size]="улы"; ArR[ArR.Size]=1;
ArP[ArP.Size]="оол"; ArR[ArR.Size]=1;
ArP[ArP.Size]="кызы"; ArR[ArR.Size]=2;
ArP[ArP.Size]="кизы"; ArR[ArR.Size]=2;
ArP[ArP.Size]="гызы"; ArR[ArR.Size]=2;
ArP[ArP.Size]="киз"; ArR[ArR.Size]=2;
ArP[ArP.Size]="кыз"; ArR[ArR.Size]=2;
//арабские - в начале отчества
ArP1[ArP1.Size]="ибн"; ArR1[ArR1.Size]=1;
ArP1[ArP1.Size]="бинти"; ArR1[ArR1.Size]=2;
ArP1[ArP1.Size]="бинт"; ArR1[ArR1.Size]=2;
SetParm(1,0); N=""; SetParm(2,N); SetParm(3,0);
i=0;
while(i<ArP.Size)
ndx=len-strlen(ArP[i])+1;
if(substr(P1,ndx)==ArP[i])
N=substr(P,1,ndx-1); if(substr(N,strlen(N),1)=="-") N=substr(N,1,strlen(N)-1); end;
N=trim(N);
SetParm(1,ArR[i]); SetParm(2,N); SetParm(3,1); return substr(P,ndx);
end;
i=i+1;
end;
i=0;
while(i<ArP1.Size)
ndx=strlen(ArP1[i]);
if(substr(P1,1,ndx)==ArP1[i])
N=substr(P,ndx+1); if(substr(N,1,1)=="-") N=substr(N,2); end;
N=trim(N);
SetParm(1,ArR1[i]); SetParm(2,N); SetParm(3,2); return substr(P,1,ndx);
end;
i=i+1;
end;
return "";
end;
Есть функция определения рода по ФИО: hl_GetRodFIO(t,delim)
Есть функция склонения ФИО по падежам:hl_ПадежФИО(t,przn,rod).
Есть функция, которая возвращает массив ФИО из произвольной строки: hlx_ArFIOFromString().
Наличие словаря позволяет делать проверку введенных ИО на валидность. Бывает девушки ошибаются при вводе. Если же ИО нет в словаре, а оператор считает, что все ОК, то ФИО пишется в лог. И я потом разбираюсь - есть такое или нет, и корежу словарь.
Вроде все, что мог по теме сказал. :)
>> Ответить
- С "оглы" не совсем так (+) ( григ 30.08.2019 07:43 )
- Корейцев по фамилии надо отлавливать (+) ( tema 29.08.2019 23:34 )
- Согласен, задача более сложная, чем разбивка строки на слова (+) ( григ 29.08.2019 08:30 )
- интересненько, но ( tema 28.08.2019 23:46 )
- поковырялся, но вариант не точный ( Andrew01 24.04.2019 12:15 )