如何使用自定义比较器对通用列表进行排序? [英] How do I sort a generic list using a custom comparer?

查看:116
本文介绍了如何使用自定义比较器对通用列表进行排序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很喜欢Delphi-newbie,我不知道如何调用记录TList的Sort方法,以便通过升序整数来对记录进行排序。
我有一个记录如下:

 键入
TMyRecord = record
str1:串;
str2:string;
intVal:integer;
结束

此类记录的通用列表:

  TListMyRecord = TList< TMyRecord> ;; 

尝试在帮助文件中找到代码示例,找到这个:

  MyList.Sort(@CompareNames); 

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

  function CompareIntVal(i1,i2:TMyRecord):整数; 
begin
结果:= i1.intVal - i2.intVal;
结束

但编译器总是抛出一个不够参数 - 当我用 open.Sort(CompareIntVal); ,这似乎很明显;所以我试图靠近帮助文件:

  function SortKB(Item1,Item2:Pointer):Integer; 
begin
结果:= PMyRecord(Item1)^。intVal - PMyRecord(Item2)^。intVal;
结束

与PMyRecord为 PMyRecord = ^ TMyRecord;



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

解决方案

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

 code> procedure Sort(const AComparer:IComparer< TMyRecord>); 

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

  var 
比较:TComparison< TMyRecord> ;;
....
比较:=
函数(const Left,Right:TMyRecord):Integer
begin
结果:= Left.intVal-Right.intVal;
结束
List.Sort(TComparer< TMyRecord> .Construct(Comparison));

我已经将比较函数写成一个匿名的方法,但是你也可以使用一个普通的旧样式的非OOP函数或一个对象的方法。



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

 比较:= 
函数(常量左,右:TMyRecord) :整数
begin
结果:= TComparer< Integer> .Default.Compare(Left.intVal,Right.intVal);
结束

调用 TComparer< Integer> .Default 反复,所以你可以将它存储在全局变量中:

  var 
IntegerComparer:IComparer< Integer> ;;
....
初始化
IntegerComparer:= TComparer< Integer> .Default;

另一个需要考虑的方法是在创建列表时传入比较器。如果你只使用这个顺序对列表进行排序,那就更方便了。

 列表:= TList< TMyRecord> .Create(TComparer< ; TMyRecord> .Construct(Comparison)); 

然后,您可以使用

  List.Sort; 


I'm kinda a Delphi-newbie and I don't get how the Sort method of a TList of Records is called in order to sort the records by ascending integer value. I have a record like the following:

 type
   TMyRecord = record
     str1: string;
     str2: string;
     intVal: integer;
   end;

And a generic list of such records:

TListMyRecord = TList<TMyRecord>;

Have tried to find a code-example in the help files and found this one:

MyList.Sort(@CompareNames);

Which I can't use, since it uses classes. So I tried to write my own compare function with a little different parameters:

function CompareIntVal(i1, i2: TMyRecord): Integer;
begin
  Result := i1.intVal - i2.intVal;
end;

But the compiler always throws a 'not enough parameters' - error when I call it with open.Sort(CompareIntVal);, which seems obvious; so I tried to stay closer to the help file:

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

with PMyRecord as PMyRecord = ^TMyRecord;

I have tried different ways of calling a function, always getting some error...

解决方案

The Sort overload you should be using is this one:

procedure Sort(const AComparer: IComparer<TMyRecord>);

Now, you can create an IComparer<TMyRecord> by calling TComparer<TMyRecord>.Construct. Like this:

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

I've written the Comparison function as an anonymous method, but you could also use a plain old style non-OOP function, or a method of an object.

One potential problem with your comparison function is that you may suffer from integer overflow. So you could instead use the default integer comparer.

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

It might be expensive to call TComparer<Integer>.Default repeatedly so you could store it away in a global variable:

var
  IntegerComparer: IComparer<Integer>;
....
initialization
  IntegerComparer := TComparer<Integer>.Default;

Another option to consider is to pass in the comparer when you create the list. If you only ever sort the list using this ordering then that's more convenient.

List := TList<TMyRecord>.Create(TComparer<TMyRecord>.Construct(Comparison));

And then you can sort the list with

List.Sort;

这篇关于如何使用自定义比较器对通用列表进行排序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆