如何在字符串列表中对数字进行排序?

Thu*_*erx 2 delphi sorting delphi-10.1-berlin

我有一个包含一些数字的字符串列表.我使用我写的冒泡排序对它们进行了排序.输出是:

18
20
3
44
53
Run Code Online (Sandbox Code Playgroud)

我不明白为什么上面输出而不是我的预期:

3
18
20
44
53
Run Code Online (Sandbox Code Playgroud)

我错过了什么?

Dav*_*nan 9

首先,您不需要编写自己的排序代码来对字符串列表中的字符串进行排序.字符串列表类附带一个sort函数.您可以使用它而不是编写自己的排序代码.

现在转到问题的关键,在程序的输出中,这些值在被视为文本时被正确排序.它们按字典或字典顺序正确排序.例如

'20' < '3'
Run Code Online (Sandbox Code Playgroud)

因为文字是按字符比较的,而且'2' < '3'.

但是您希望将值排序为数字.在这种情况下,您应首先将它们转换为数字,然后对数字而不是文本进行排序.这样做:

  • 创建一个数组TArray<Integer>,其大小可以保存字符串列表的每个值.
  • 使用填充数组StrToInt将列表中的每个字符串转换为整数.
  • 排序使用阵列TArray.Sort<T>Generics.Collections单元.

或许更好的方法是不要将值存储为文本.将数据保存为数组或整数列表,然后对其进行排序.毕竟,如果您的数据是整数值,那么将它们存储起来是有意义的.

如果您将数据保存在数组中,则可以按上述方法进行排序TArray.Sort<T>.或者,如果你使用,TList<T>那么利用它的Sort方法.


Rem*_*eau 7

正如David在他的回答中解释的那样,您正在将字符串排序为文本字符,而不是整数。

您可以使用该TStringList.CustomSort()方法,在比较字符串时将其转换为整数:

function MySortProc(List: TStringList; Index1, Index2: Integer): Integer;
var
  Value1, Value2: Integer;
begin
  Value1 := StrToInt(List[Index1]);
  Value2 := StrToInt(List[Index2]);
  if Value1 < Value2 then
    Result := -1
  else if Value2 < Value1 then
    Result := 1
  else
    Result := 0;
end;

SL.Add('18');
SL.Add('20');
SL.Add('3');
SL.Add('44');
SL.Add('53');
SL.CustomSort(MySortProc);
Run Code Online (Sandbox Code Playgroud)

或者,将实际的整数值存储在Objects属性中,以便在排序时不必连续转换字符串:

function MySortProc(List: TStringList; Index1, Index2: Integer): Integer;
var
  Value1, Value2: Integer;
begin
  Value1 := Integer(List.Objects[Index1]);
  Value2 := Integer(List.Objects[Index2]);
  if Value1 < Value2 then
    Result := -1
  else if Value2 < Value1 then
    Result := 1
  else
    Result := 0;
end;

SL.Add('18', TObject(18));
SL.Add('20', TObject(20));
SL.Add('3', TObject(3));
SL.Add('44', TObject(44));
SL.Add('53', TObject(53));
SL.CustomSort(MySortProc);
Run Code Online (Sandbox Code Playgroud)

或者,您可以StrCmpLogicalW()用来让Windows为您比较字符串:

function StrCmpLogicalW(const psz1, psz2: PWideChar): Integer; stdcall; external 'Shlwapi.dll';

function MySortProc(List: TStringList; Index1, Index2: Integer): Integer;
begin
  Result := StrCmpLogicalW(PChar(List[Index1]), PChar(List[Index2]));
end;

SL.Add('18');
SL.Add('20');
SL.Add('3');
SL.Add('44');
SL.Add('53');
SL.CustomSort(MySortProc);
Run Code Online (Sandbox Code Playgroud)

  • 我认为建议在TObject字段中保留整数值确实是一个坏主意,它可能会导致人们陷入危险。有TList &lt;integer&gt; / TArray &lt;integer&gt;等。自定义排序函数也比指针和整数类型之间的转换要优雅得多。 (3认同)
  • @Wosi我们已经进行了对话。雷米的答案原本就是这样做的。但是请问问自己,该程序的输出是什么:`{$ APPTYPE CONSOLE} var i,j:Integer; 开始我:=高(整数); j:=低(整数); Writeln(ij); 结束。`它输出正值还是负值?你怎么看?这是一种非常常见的反模式。 (3认同)