DELPHI STRING: вытащить фамилию из полного имени - PullRequest
7 голосов
/ 27 мая 2011

Я пытаюсь манипулировать строкой и извлекать из нее только определенные данные.Я должен сделать это на записи, извлеченной из базы данных, которая дает мне полное имя человека.Мне нужно извлечь только фамилию из строки и сохранить ее как переменную.Есть ли способ, которым я могу это сделать?

Пример: SQL-запрос извлекает полное поле «Мэри Эллен Джонс». Мне нужно извлечь только строку Джонса из строки, чтобы я мог сохранить ее в переменной для дальнейшей обработки.AnsiRightStr будет работать, но проблема состоит в том, чтобы дать ему целое число, заданное справа.Может быть, способ подсчета символов после последнего пробела позволяет мне использовать AnsiRightStr (string, int) для этого?Любая помощь приветствуется.

Дополнительная мысль: возможно ли будет заменить пробелы разделителем say :: и затем проанализировать эти данные в Stringlist, а затем разрешить мне вытянуть последний индекс списка строк?

Несколько действительных вариантов были представлены до сих пор.Никто из них не решит ситуацию, если скажет, что имя Нечто вроде «Джон Сент-Джеймс-младший».Это невозможно?

Ответы [ 4 ]

7 голосов
/ 27 мая 2011

Вы можете использовать функцию LastDelimiter для получения последней позиции пробела, а затем с помощью функции copy извлечь подстроку.

uses
  SysUtils;


var
  Name      : string;
  p         : Integer;
  ShortName : string;
begin
  Name:='Mary Ellen Jones';
  //You can call trim to avoid problems with ending spaces in this case is not necesary, just is a test
  //Name:=Trim(Name); 
  //get the last space position
  p:=LastDelimiter(' ',Name);
  //get the name
  ShortName:=Copy(Name,p+1,length(Name)-p);
end;

или используя функцию

function GetLast(const Name:string) : string;
var
  p : Integer;
begin
  Result:=Trim(Name);
  p:=LastDelimiter(' ',Result);
  Result:=Copy(Result,p+1,length(Result)-p);
end;
6 голосов
/ 27 мая 2011
function GetLastWord(const Str: string): string;
var
  p: integer;
  i: Integer;
const
  SPACE = #$20;
begin
  p := 1;
  for i := length(Str) downto 1 do
    if Str[i] = SPACE then
    begin
      p := i + 1;
      break;
    end;
  result := Copy(Str, p, MaxInt);
end;

Это не удастся, если строка заканчивается (случайным) пробелом, как 'Andreas Rejbrand'.Эта более надежная версия также справится с этим делом:

function GetLastWord(const Str: string): string;
var
  p: integer;
  i: Integer;
  FoundNonSpace: boolean;
const
  SPACE = #$20;
begin
  p := 1;
  FoundNonSpace := false;
  for i := length(Str) downto 1 do
    if (Str[i] = SPACE) and FoundNonSpace then
    begin
      p := i + 1;
      break
    end
    else if Str[i] <> SPACE then
      FoundNonSpace := true;
  result := TrimRight(Copy(Str, p, MaxInt));
end;
5 голосов
/ 27 мая 2011

Что, если фамилия произнесет "Сент-Джеймс", чтобы объяснить это?

Вот мой подход.

  1. Составить список фамилий-маркеров
  2. Поиск в этом списке в порядке предпочтения
  3. Как только совпадение найдено, отметьте это как начало фамилии
  4. Возвращает подстроку, начиная с этой позиции.
var
  LastNameMarkers: TStringList = nil;
  SuffixFix: TStringList = nil;
procedure InitLists;
begin
  LastNameMarkers:= TStringList.Create;
  //LastNameMarkers.LoadFromFile('c:\markers.txt');
  LastNameMarkers.Add(' St.');
  LastnameMarkers.Add(' Mc');
  LastNameMarkers.Add(' '); //Marker of last resort.
  SuffixFix:= TStringList.Create;
  SuffixFix.Add(' Jr.');
  SuffixFix.Add(' Sr.');
end;

function GetLastName(FullName: string): string;
var
  i: integer;
  start: integer;
  found: boolean;
  ReplaceWith: string;
begin
  if LastNameMarkers = nil then InitLists;

  //Fix suffixes
  i:= 0;
  found:= false;
  while (i < SuffixFix.Count) and not found do begin
    start:= pos(lower(LastNameMarkers[i]),lower(Fullname));
    found:= Start > 0;
    Inc(i);
  end; {while}
  if Found then begin 
    Dec(i);
    ReplaceWith:= StringReplace(Suffix[i], ' ', '_',[]);
    FullName:= StringReplace(FullName, SuffixFix[i], ReplaceWith,[]);
  end; {if}

  //Look for lastnames 
  i:= 0;
  found:= false;
  while (i < LastNameMarkers.Count) and not found do begin
    start:= pos(LastNameMarkers[i],Fullname);
    found:= Start > 0;
    Inc(i);
  end; {while}

  if found then Result:= RightStr(FullName, Length(FullName)- Start + 2)
  else Result:= '';

  StringReplace(Result, '_', ' ',[]);
end;

Я не имел дело с прописными и строчными буквами должным образом, но я надеюсь, что вы поняли.

0 голосов
/ 29 мая 2011
function TfrmCal.GetLastName(FullName: string): string;
var
    i: integer;
    found: boolean;
    suffix: string;
    marker: string;
begin
    // Build the lists for the compare.
    InitLists;

    // Look at Suffixes and attach them to the LastName
    i := 0;
    found := False;
    while (i < SuffixFix.Count) do
    begin
        if AnsiContainsStr(FullName, SuffixFix[i]) then
        begin
            suffix := '::' + trim(SuffixFix[i]);
            FullName := ReplaceStr(FullName, SuffixFix[i], suffix);
            found := True;
        end;
        inc(i);
        if found then
            break;
    end;
    // Look for LastName Markers
    i := 0;
    found := False;
    while (i < LastNameMarkers.Count) do
    begin
        if AnsiContainsStr(FullName, LastNameMarkers[i]) then
        begin
            marker := trimright(LastNameMarkers[i]) + '::';
            FullName := ReplaceStr(FullName, LastNameMarkers[i], marker);
            found := True;
        end;
        inc(i);
        if found then
            break;
    end;

    FullName := GetLastWord(FullName);
    FullName := ReplaceStr(FullName, '::', ' ');
    LastNameMarkers.Clear;
    SuffixFix.Clear;
    Result := FullName;
end;

function TfrmCal.GetLastWord(const Str: string): string;
var
    p: integer;
    i: integer;
const
    SPACE = #$20;
begin
    p := 1;
    for i := Length(Str) downto 1 do
        if Str[i] = SPACE then
        begin
            p := i + 1;
            break;
        end;
    Result := Copy(Str, p, MaxInt);
end;

Эти две функции вместе выполняют то, что мне нужно было сделать.Есть также функция initlists, которая неуклюжа и уродлива, и мне нужно поработать, чтобы я не разместил ее здесь.

...