在空白之后按第一个字符对TStringList进行排序

时间:2014-09-24 11:38:52

标签: delphi sorting

我在Delphi中有一个TStringList。 插入项目后,我调用.sort程序对项目进行排序。 物品是名字后跟姓氏。例如:" John Smith"。 我想按姓氏对项目进行排序。我的意思是空间后的第一个角色。  我怎么能这样做?

并且这些项目也可以是像波斯语字符一样的unicode字符串。

3 个答案:

答案 0 :(得分:5)

我使用TStringList的{​​{3}}方法提供自定义比较功能。首先,让我们想象一下我们已经有了比较功能:

function NameCompareFunc(List: TStringList; Index1, Index2: Integer): Integer;
begin
  Result := ...;
end;

此函数将(在适当的时候)返回负值表示小于,正值表示大于零,零表示相等。

然后我们按如下方式对列表进行排序:

List.CustomSort(NameCompareFunc);

所以,这很容易做到。但是我们如何实施NameCompareFunc?首先,让我们将名称分为姓氏和其他名称。

procedure SplitName(const Name: string; out Last, Rest: string);
var
  P: Integer;
begin
  P := Pos(' ', Name);
  if P = 0 then begin
    Last := Trim(Name);
    Rest := '';
  end else begin
    Last := Trim(Copy(Name, P+1, MaxInt));
    Rest := Trim(Copy(Name, 1, P-1));
  end;
end;

这是分割名称的一种非常天真的方式。您可能希望从名称末尾开始搜索分隔符,但我们会让您决定如何执行此操作。

现在我们可以实现比较功能:

function NameCompareFunc(List: TStringList; Index1, Index2: Integer): Integer;
var
  Last1, Last2, Rest1, Rest2: string;
begin
  SplitName(List[Index1], Last1, Rest1);
  SplitName(List[Index2], Last2, Rest2);
  Result := AnsiCompareText(Last1, Last2);
  if Result = 0 then begin
    Result := AnsiCompareText(Rest1, Rest2);
  end;
end;

一些注意事项:

  1. 我假设名称比较应始终不区分大小写。
  2. 我们使用AnsiCompareText执行区域设置感知比较。
  3. 如果我们遇到两个姓氏相同的名字,那么我们会对名称的其余部分进行二次比较。

答案 1 :(得分:3)

您可以使用Stringlist的CustomSort方法:

function LastNameCompareStrings(List: TStringList; Index1, Index2: Integer): Integer;
var
  S1, S2: string;
  SpaceIndex: Integer;
begin
  S1 := List[Index1];
  SpaceIndex := Pos(' ', S1);
  if SpaceIndex <> 0 then
    S1 := Copy(S1, 1, SpaceIndex - 1);

  S2 := List[Index2];
  SpaceIndex := Pos(' ', S2);
  if SpaceIndex <> 0 then
    S2 := Copy(S2, 1, SpaceIndex - 1);

  if List.CaseSensitive then
    Result := AnsiCompareStr(S1, S2)
  else
    Result := AnsiCompareText(S1, S2);
end;

procedure TForm7.ButtonFirstNameClick(Sender: TObject);
begin
  NameBuffer.Sort;
  Memo1.Lines.Assign(NameBuffer);
end;

procedure TForm7.ButtonLastNameClick(Sender: TObject);
begin
  NameBuffer.CustomSort(@LastNameCompareStrings);
  Memo1.Lines.Assign(NameBuffer);
end;

我的例子我在StringList中有你所有的名字,叫做NameBuffer。然后我在表单中添加了两个按钮,我将其分类为mylist,并在屏幕上显示结果。

答案 2 :(得分:0)

您可以迭代StringList的每个项目(让我们称之为FullNames), 拆分每个字符串并将“拆分”放在两个可以调用的新单独的字符串列表中 FirstNameList和LastNameList。

现在创建第三个字符串列表,您可以调用ReverseFirstLast, 并将LastNameList中的项与FirstNameList合并,并将它们放在ReverseNames中。

现在您的所有名称都按相反的顺序排列。姓氏优先,姓氏最后。

您现在可以对ReverseFirstLast列表进行排序,并再次执行split&amp; combine方法再次撤消订单并维护排序。

这是一种方法,可以让一个粗略的方法启动并运行。