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...
Sort() Method Set -1. List<T>. Sort() Method is used to sort the elements or a portion of the elements in the List<T> using either the specified or default IComparer<T> implementation or a provided Comparison<T> delegate to compare list elements.
Sort(IComparer) This method is used to sort the elements in the entire ArrayList using the specified comparer. This method is an O(n log n) operation, where n is Count; in the worst case, it is an O(n^2) operation. Syntax: public virtual void Sort (IComparer comparer);
You cannot sort a list by an array-based field, such as a Glide list.
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;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With