Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DELPHI STRING: Pull a last name from a full name

I am trying to manipulate a string and pull only certain data from it. I need to do this on a record pulled from a database that gives me the full name of a person. I need to pull only the last name from the string and store it as a variable. Is there a way that I can do this?

Example: SQL query pulls the full field "Mary Ellen Jones" I need to extract only the Jones from the string so I can store it in a variable for further processing.

I thought maybe AnsiRightStr would work but the problem is needing to give it a set integer to pull from the right. Maybe a way to count the characters after the final space allowing me to use AnsiRightStr(string,int) for this? Any help at all is appreciated.

Additional thought: Would replacing the spaces with a delimiter say :: and then parsing that data into a Stringlist followed by allowing me to pull the last index of the string list be possible?

Several valid options have been presented so far. None of them address the situation if say the name is Something like "John St. James, Jr." Is this impossible?

like image 257
James West Avatar asked May 27 '11 17:05

James West


3 Answers

you can use the LastDelimiter function to get the last space position and then with the copy function extract the substring.

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;

or using a function

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;
like image 112
RRUZ Avatar answered Nov 04 '22 14:11

RRUZ


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;

This will fail if the string ends with (an accidental) space, as 'Andreas Rejbrand '. This more robust version will handle this case too:

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;
like image 32
Andreas Rejbrand Avatar answered Nov 04 '22 14:11

Andreas Rejbrand


What if the last name is say "St. James" any way to account for that?

Here's my approach.

  1. Make a list of lastname-markers
  2. Search that list in order of preference
  3. As soon as a match is found, mark that as the start of last name
  4. Return substring starting from that pos.
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;

I haven't dealt with upper and lowercase properly, but I hope you get the idea.

like image 32
Johan Avatar answered Nov 04 '22 16:11

Johan