Je suis un peu un débutant dans Delphi et je ne comprends pas comment la méthode de tri d'une TList of Records est appelée afin de trier les enregistrements par la valeur entière croissante .
type
TMyRecord = record
str1: string;
str2: string;
intVal: integer;
end;
Et une liste générique de tels enregistrements:
TListMyRecord = TList<TMyRecord>;
J'ai essayé de trouver un exemple de code dans les fichiers d'aide et j'ai trouvé celui-ci:
MyList.Sort(@CompareNames);
Ce que je ne peux pas utiliser, car il utilise des classes. J'ai donc essayé d'écrire ma propre fonction de comparaison avec un peu de paramètres différents:
function CompareIntVal(i1, i2: TMyRecord): Integer;
begin
Result := i1.intVal - i2.intVal;
end;
Mais le compilateur lance toujours un 'pas assez de paramètres' - une erreur lorsque je l'appelle avec open.Sort(CompareIntVal);
, ce qui semble évident; alors j'ai essayé de rester plus près du fichier d'aide:
function SortKB(Item1, Item2: Pointer): Integer;
begin
Result:=PMyRecord(Item1)^.intVal - PMyRecord(Item2)^.intVal;
end;
avec PMyRecord en tant que PMyRecord = ^TMyRecord;
J'ai essayé différentes manières d'appeler une fonction, en obtenant toujours des erreurs ...
La surcharge Sort
que vous devriez utiliser est la suivante:
procedure Sort(const AComparer: IComparer<TMyRecord>);
Maintenant, vous pouvez créer un IComparer<TMyRecord>
en appelant TComparer<TMyRecord>.Construct
. Comme ça:
var
Comparison: TComparison<TMyRecord>;
....
Comparison :=
function(const Left, Right: TMyRecord): Integer
begin
Result := Left.intVal-Right.intVal;
end;
List.Sort(TComparer<TMyRecord>.Construct(Comparison));
J'ai écrit la fonction Comparison
en tant que méthode anonyme, mais vous pouvez également utiliser une fonction non-OOP de style ancien ou une méthode d'objet.
Un problème potentiel avec votre fonction de comparaison est que vous pouvez souffrir d'un dépassement d'entier. Vous pouvez donc utiliser le comparateur d'entiers par défaut.
Comparison :=
function(const Left, Right: TMyRecord): Integer
begin
Result := TComparer<Integer>.Default.Compare(Left.intVal, Right.intVal);
end;
Il peut être coûteux d'appeler plusieurs fois le TComparer<Integer>.Default
pour pouvoir le stocker dans une variable globale:
var
IntegerComparer: IComparer<Integer>;
....
initialization
IntegerComparer := TComparer<Integer>.Default;
Une autre option à considérer consiste à transmettre le comparateur lorsque vous créez la liste. Si vous ne triez jamais la liste en utilisant cet ordre, c'est plus pratique.
List := TList<TMyRecord>.Create(TComparer<TMyRecord>.Construct(Comparison));
Et puis vous pouvez trier la liste avec
List.Sort;
La réponse concise:
uses
.. System.Generics.Defaults // Contains TComparer
myList.Sort(
TComparer<TMyRecord>.Construct(
function(const Left, Right: TMyRecord): Integer
begin
Result := Left.intVal - Right.intVal;
end
)
);
J'ai trouvé une fonction de tri modifiée beaucoup plus simple pour alphabétiser une liste d'enregistrements ou une liste non standard d'éléments.
Exemple
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;
et la fonction à appeler pour trier votre liste
Contacts.Sort(@CompareNames);
Je souhaite partager ma solution (sur la base des informations que j'ai rassemblées ici).
C'est une configuration standard. Une classe filedata qui contient les données d'un seul fichier dans un TObjectList générique. La liste comporte les deux attributs privés fCurrentSortedColumn et fCurrentSortAscending pour contrôler l'ordre de tri. La méthode AsString est le chemin et le nom du fichier combinés.
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;