我是一个Delphi新手,我不知道如何调用TList of Records的Sort方法,以便按升序整数值对记录进行排序。 我有如下记录:
type
TMyRecord = record
str1: string;
str2: string;
intVal: integer;
end;
此类记录的通用列表:
TListMyRecord = TList<TMyRecord>;
尝试在帮助文件中找到代码示例并找到了这个:
MyList.Sort(@CompareNames);
我不能使用,因为它使用类。所以我尝试用一些不同的参数编写自己的比较函数:
function CompareIntVal(i1, i2: TMyRecord): Integer;
begin
Result := i1.intVal - i2.intVal;
end;
但是编译器总是抛出“不够的参数” - 当我用open.Sort(CompareIntVal);
调用它时出错,这看起来很明显;所以我试图更接近帮助文件:
function SortKB(Item1, Item2: Pointer): Integer;
begin
Result:=PMyRecord(Item1)^.intVal - PMyRecord(Item2)^.intVal;
end;
将PMyRecord设为PMyRecord = ^TMyRecord;
我尝试了不同的方法来调用函数,总是会出现一些错误......
答案 0 :(得分:46)
你应该使用的Sort
重载就是这个:
procedure Sort(const AComparer: IComparer<TMyRecord>);
现在,您可以通过调用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));
我已将Comparison
函数编写为匿名方法,但您也可以使用普通的旧式非OOP函数或对象的方法。
比较函数的一个潜在问题是您可能会遇到整数溢出。所以你可以使用默认的整数比较器。
Comparison :=
function(const Left, Right: TMyRecord): Integer
begin
Result := TComparer<Integer>.Default.Compare(Left.intVal, Right.intVal);
end;
重复调用TComparer<Integer>.Default
可能会很昂贵,因此您可以将其存储在全局变量中:
var
IntegerComparer: IComparer<Integer>;
....
initialization
IntegerComparer := TComparer<Integer>.Default;
要考虑的另一个选择是在创建列表时传入比较器。如果您只使用此排序对列表进行排序,则更方便。
List := TList<TMyRecord>.Create(TComparer<TMyRecord>.Construct(Comparison));
然后您可以使用
对列表进行排序List.Sort;
答案 1 :(得分:5)
简明的回答:
uses
.. System.Generics.Defaults // Contains TComparer
myList.Sort(
TComparer<TMyRecord>.Construct(
function(const Left, Right: TMyRecord): Integer
begin
Result := Left.intVal - Right.intVal;
end
)
);
答案 2 :(得分:2)
我找到了一个更简单的修改排序函数来按字母顺序排列记录的TList或非标准的项目列表。
实施例
PList = ^TContact;
TContact = record //Record for database of user contact records
firstname1 : string[20];
lastname1 : string[20];
phonemobile : Integer; //Fields in the database for contact info
phonehome : Integer;
street1 : string;
street2 : string;
type
TListSortCompare = function (Item1,
Item2: TContact): Integer;
var
Form1: TForm1;
Contact : PList; //declare record database for contacts
arecord : TContact;
Contacts : TList; //List for the Array of Contacts
function CompareNames(i1, i2: TContact): Integer;
begin
Result := CompareText(i1.lastname1, i2.lastname1) ;
end;
以及调用列表排序的函数
Contacts.Sort(@CompareNames);
答案 3 :(得分:0)
我想分享我的解决方案(基于我在这里收集的输入)。
这是标准设置。一个filedata类,用于保存通用TObjectList中单个文件的数据。该列表具有两个私有属性fCurrentSortedColumn和fCurrentSortAscending来控制排序顺序。 AsString方法是路径和文件名的组合。
function TFileList.SortByColumn(aColumn: TSortByColums): boolean;
var
Comparison: TComparison<TFileData>;
begin
result := false;
Comparison := nil;
case aColumn of
sbcUnsorted : ;
sbcPathAndName: begin
Comparison := function(const Left, Right: TFileData): integer
begin
Result := TComparer<string>.Default.Compare(Left.AsString,Right.AsString);
end;
end;
sbcSize : begin
Comparison := function(const Left, Right: TFileData): integer
begin
Result := TComparer<int64>.Default.Compare(Left.Size,Right.Size);
if Result = 0 then
Result := TComparer<string>.Default.Compare(Left.AsString,Right.AsString);
end;
end;
sbcDate : begin
Comparison := function(const Left, Right: TFileData): integer
begin
Result := TComparer<TDateTime>.Default.Compare(Left.Date,Right.Date);
if Result = 0 then
Result := TComparer<string>.Default.Compare(Left.AsString,Right.AsString);
end;
end;
sbcState : begin
Comparison := function(const Left, Right: TFileData): integer
begin
Result := TComparer<TFileDataTestResults>.Default.Compare(Left.FileDataResult,Right.FileDataResult);
if Result = 0 then
Result := TComparer<string>.Default.Compare(Left.AsString,Right.AsString);
end;
end;
end;
if assigned(Comparison) then
begin
Sort(TComparer<TFileData>.Construct(Comparison));
// Control the sort order
if fCurrentSortedColumn = aColumn then
fCurrentSortAscending := not fCurrentSortAscending
else begin
fCurrentSortedColumn := aColumn;
fCurrentSortAscending := true;
end;
if not fCurrentSortAscending then
Reverse;
result := true;
end;
end;