Разбивка строки ФИО на Фамилию Имя Отчество

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;

        >> Ответить
    • Развернуть Универсальная разбивалка строк в массив ( 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 );
      
      Функция нечувствительна к отсутствию отчества ( да и имени с фамилией )) ), количеству пробелов до, после и между частями ФИО.
      >> Ответить
    • Развернуть Это достаточно трудная задача и в общем случае она не решается. ( 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().

              Наличие словаря позволяет делать проверку введенных ИО на валидность. Бывает девушки ошибаются при вводе. Если же ИО нет в словаре, а оператор считает, что все ОК, то ФИО пишется в лог. И я потом разбираюсь - есть такое или нет, и корежу словарь.
              Вроде все, что мог по теме сказал. :)

              >> Ответить