如何使用自定义比较器对通用列表进行排序? [英] How do I sort a generic list using a custom comparer?
问题描述
我有一个记录如下:
键入
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屋!