Reputation: 85
I'm using Generics.Collections.TList and Sort method. It is working ok, but I want to sort nulls or empty values last. In ascending and descending sort order. How to implement that?
Here is my sorting function:
function TForm.SortByColumn(ColumnID: integer; SortDirRev: integer):boolean;
var
Comparison: TComparison<TSymData>;
begin
Result := false;
Comparison := nil;
if ColumnID = 0 then
begin
Comparison := function(const Left, Right: TSymData): integer
begin
Result := SortDirRev * TComparer<string>.Default.Compare(Left.Name,Right.Name);
end;
end
else
begin
Comparison := function(const Left, Right: TSymData): integer
begin
Result := SortDirRev * TComparer<string>.Default.Compare(Left.Sub[ColumnID-1],Right.Sub[ColumnID-1]);
end;
end;
if assigned(Comparison) then
FSymList.Sort(TComparer<TSymData>.Construct(Comparison));
end;
Upvotes: 2
Views: 1386
Reputation: 108929
You just need to provide a comparison function which takes empty values into account.
A comparison function is a function that takes two items A and B and returns -1 if A should go before B, +1 if A should go after B, and 0 if A and B are considered equal.
For example, to sort a list L
of strings using the standard string comparer, you can do (just for reference)
L.Sort(
TComparer<string>.Construct(
function(const Left, Right: string): Integer
begin
Result := CompareStr(Left, Right)
end
)
);
To sort according to string length, do
L.Sort(
TComparer<string>.Construct(
function(const Left, Right: string): Integer
begin
Result := CompareValue(Left.Length, Right.Length)
end
)
);
Now, if you want to sort the strings normally, except that you explicitly require all empty strings to go first, you can do
L.Sort(
TComparer<string>.Construct(
function(const Left, Right: string): Integer
begin
if Left.IsEmpty and not Right.IsEmpty then
Result := -1
else if not Left.IsEmpty and Right.IsEmpty then
Result := +1
else
Result := CompareStr(Left, Right)
end
)
);
To have the empty strings last, do
L.Sort(
TComparer<string>.Construct(
function(const Left, Right: string): Integer
begin
if Left.IsEmpty and not Right.IsEmpty then
Result := +1
else if not Left.IsEmpty and Right.IsEmpty then
Result := -1
else
Result := CompareStr(Left, Right)
end
)
);
Upvotes: 10