lke*_*ler 13 delphi sorting ansi tstringlist
我有一个简单的TStringList.我做了一个TStringList.Sort.
然后我注意到下划线"_"在大写字母"A"之前排序.这与排序相同文本并在A之后排序_的第三方软件包形成对比.
根据ANSI字符集,AZ是字符65 - 90,_是95.所以看起来第三方包使用该顺序而TStringList.Sort不是.
我深入研究了TStringList.Sort的内容,并使用AnsiCompareStr(Case Sensitive)或AnsiCompareText(Case Insensitive)进行排序.我尝试了两种方法,将我的StringList的CaseSensitive值设置为true,然后设置为false.但在这两种情况下,"_"首先排序.
我无法想象这是TStringList中的一个错误.所以这里肯定有其他东西我没有看到.可能是什么?
我真正需要知道的是如何让我的TStringList进行排序,使其与其他包的顺序相同.
作为参考,我使用Delphi 2009,我在我的程序中使用Unicode字符串.
所以这里的最终答案是覆盖Ansi与你想要的任何东西比较(例如非ansi比较),如下所示:
type
TMyStringList = class(TStringList)
protected
function CompareStrings(const S1, S2: string): Integer; override;
end;
function TMyStringList.CompareStrings(const S1, S2: string): Integer;
begin
if CaseSensitive then
Result := CompareStr(S1, S2)
else
Result := CompareText(S1, S2);
end;
Run Code Online (Sandbox Code Playgroud)
Jer*_*ers 36
定义"正确".
i18n排序完全取决于您的语言环境.
所以我完全同意PA这不是一个错误:默认排序行为的工作原理是为了让i18n正常工作.
像Gerry提到的那样,TStringList.Sort使用AnsiCompareStr和AnsiCompareText(我将在几行中解释它是如何做到的).
但是:TStringList很灵活,它包含Sort,CustomSort和CompareStrings,它们都是虚拟的(所以你可以在后代类中覆盖它们)
此外,当你调用CustomSort时,你可以插入自己的Compare函数.
在这个答案是一个比较功能,它做你想要的:
CustomSort定义如下:
procedure TStringList.CustomSort(Compare: TStringListSortCompare);
begin
if not Sorted and (FCount > 1) then
begin
Changing;
QuickSort(0, FCount - 1, Compare);
Changed;
end;
end;
Run Code Online (Sandbox Code Playgroud)
默认情况下,Sort方法有一个非常简单的实现,传递一个名为StringListCompareStrings的默认Compare函数:
procedure TStringList.Sort;
begin
CustomSort(StringListCompareStrings);
end;
Run Code Online (Sandbox Code Playgroud)
因此,如果您定义自己的TStringListSortCompare兼容的比较方法,那么您可以定义自己的排序.
TStringListSortCompare定义为采用TStringList的全局函数和引用要比较的项的两个索引:
type
TStringListSortCompare = function(List: TStringList; Index1, Index2: Integer): Integer;
Run Code Online (Sandbox Code Playgroud)
您可以使用StringListCompareStrings作为实现自己的指南:
function StringListCompareStrings(List: TStringList; Index1, Index2: Integer): Integer;
begin
Result := List.CompareStrings(List.FList^[Index1].FString,
List.FList^[Index2].FString);
end;
Run Code Online (Sandbox Code Playgroud)
因此,默认情况下TStringList.Sort遵循TList.CompareStrings:
function TStringList.CompareStrings(const S1, S2: string): Integer;
begin
if CaseSensitive then
Result := AnsiCompareStr(S1, S2)
else
Result := AnsiCompareText(S1, S2);
end;
Run Code Online (Sandbox Code Playgroud)
然后使用底层 Windows API函数CompareString和默认用户区域设置LOCALE_USER_DEFAULT:
function AnsiCompareStr(const S1, S2: string): Integer;
begin
Result := CompareString(LOCALE_USER_DEFAULT, 0, PChar(S1), Length(S1),
PChar(S2), Length(S2)) - 2;
end;
function AnsiCompareText(const S1, S2: string): Integer;
begin
Result := CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, PChar(S1),
Length(S1), PChar(S2), Length(S2)) - 2;
end;
Run Code Online (Sandbox Code Playgroud)
最后你需要比较功能.再次限制:
这是代码:
function StringListCompareStringsByOrdinalCharacterValue(List: TStringList; Index1, Index2: Integer): Integer;
var
First: string;
Second: string;
begin
First := List[Index1];
Second := List[Index2];
if List.CaseSensitive then
Result := CompareStr(First, Second)
else
Result := CompareText(First, Second);
end;
Run Code Online (Sandbox Code Playgroud)
Delphi没有关闭,恰恰相反:通常它是一个非常灵活的架构.
通常只需要挖掘一下,看看你可以在哪里融入这种灵活性.
--jeroen
| 归档时间: |
|
| 查看次数: |
15146 次 |
| 最近记录: |