如何使用自定义比较器对通用列表进行排序?

p1.*_*1.e 33 delphi sorting

我有点像Delphi-newbie,我不知道如何调用TList of Records的Sort方法,以便按升序整数值对记录进行排序.我有如下记录:

 type
   TMyRecord = record
     str1: string;
     str2: string;
     intVal: integer;
   end;
Run Code Online (Sandbox Code Playgroud)

以及此类记录的通用列表:

TListMyRecord = TList<TMyRecord>;
Run Code Online (Sandbox Code Playgroud)

试图在帮助文件中找到代码示例并找到以下代码:

MyList.Sort(@CompareNames);
Run Code Online (Sandbox Code Playgroud)

我不能使用,因为它使用类.所以我尝试用一​​些不同的参数编写自己的比较函数:

function CompareIntVal(i1, i2: TMyRecord): Integer;
begin
  Result := i1.intVal - i2.intVal;
end;
Run Code Online (Sandbox Code Playgroud)

但是编译器总是抛出"不够的参数" - 当我调用它时出错open.Sort(CompareIntVal);,这看起来很明显; 所以我试图更接近帮助文件:

function SortKB(Item1, Item2: Pointer): Integer;
begin
  Result:=PMyRecord(Item1)^.intVal - PMyRecord(Item2)^.intVal;
end;
Run Code Online (Sandbox Code Playgroud)

与PMyRecord一样 PMyRecord = ^TMyRecord;

我尝试了不同的方法调用函数,总是得到一些错误......

Dav*_*nan 48

Sort您应该使用的重载是这个:

procedure Sort(const AComparer: IComparer<TMyRecord>);
Run Code Online (Sandbox Code Playgroud)

现在,您可以IComparer<TMyRecord>通过调用创建TComparer<TMyRecord>.Construct.像这样:

var
  Comparison: TComparison<TMyRecord>;
....
Comparison := 
  function(const Left, Right: TMyRecord): Integer
  begin
    Result := Left.intVal-Right.intVal;
  end;
List.Sort(TComparer<TMyRecord>.Construct(Comparison));
Run Code Online (Sandbox Code Playgroud)

我已将该Comparison函数编写为匿名方法,但您也可以使用普通的旧式非OOP函数或对象的方法.

比较函数的一个潜在问题是您可能遇到整数溢出.所以你可以使用默认的整数比较器.

Comparison := 
  function(const Left, Right: TMyRecord): Integer
  begin
    Result := TComparer<Integer>.Default.Compare(Left.intVal, Right.intVal);
  end;
Run Code Online (Sandbox Code Playgroud)

TComparer<Integer>.Default重复调用可能很昂贵,因此您可以将其存储在全局变量中:

var
  IntegerComparer: IComparer<Integer>;
....
initialization
  IntegerComparer := TComparer<Integer>.Default;
Run Code Online (Sandbox Code Playgroud)

另一个需要考虑的选择是在创建列表时传入比较器.如果您只使用此排序对列表进行排序,则更方便.

List := TList<TMyRecord>.Create(TComparer<TMyRecord>.Construct(Comparison));
Run Code Online (Sandbox Code Playgroud)

然后你可以对列表进行排序

List.Sort;
Run Code Online (Sandbox Code Playgroud)


Ian*_*oyd 7

简洁的答案:

uses
  .. System.Generics.Defaults // Contains TComparer

myList.Sort(
  TComparer<TMyRecord>.Construct(
    function(const Left, Right: TMyRecord): Integer
    begin
      Result := Left.intVal - Right.intVal;
    end
  )
);
Run Code Online (Sandbox Code Playgroud)