DELPHI STRING:从全名中提取姓氏

时间:2011-05-27 17:41:40

标签: delphi string delphi-2009

我正在尝试操纵字符串并仅从中拉取某些数据。我需要在从数据库中提取的记录中执行此操作,该数据库为我提供了一个人的全名。我只需从字符串中提取姓氏并将其存储为变量。有没有办法可以做到这一点?

示例:SQL查询提取完整字段“Mary Ellen Jones”我需要仅从字符串中提取Jones,以便将其存储在变量中以供进一步处理。

我想也许AnsiRightStr可以工作,但问题是需要给它一个设置整数从右边拉。也许在最终空间之后计算字符的方法允许我为此使用AnsiRightStr(string,int)?任何帮助都表示赞赏。

额外的想法:用分隔符替换空格是否说::然后将该数据解析为Stringlist,然后允许我拉出字符串列表的最后一个索引?

到目前为止已经提出了几个有效的选项。如果说名字是“John St. James,Jr。”之类的东西,他们都没有解决这个问题。这不可能吗?

4 个答案:

答案 0 :(得分:7)

您可以使用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;

答案 1 :(得分:6)

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;

答案 2 :(得分:5)

  

如果姓氏以“圣詹姆斯”的方式说明怎么办?

这是我的方法。

  1. 列出lastname-markers
  2. 按优先顺序搜索该列表
  3. 一旦找到匹配项,请将其标记为姓氏的开头
  4. 从该位置开始返回子串。
  5. 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;
    

    我没有正确处理大写和小写,但我希望你明白这一点。

答案 3 :(得分:0)

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函数,这是笨重和丑陋的,我需要继续工作所以我没有在这里发布。