Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delphi - generic TList sort

Tags:

delphi

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;
like image 910
Ivan Avatar asked Mar 23 '26 20:03

Ivan


1 Answers

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
  )
);
like image 89
Andreas Rejbrand Avatar answered Mar 26 '26 15:03

Andreas Rejbrand



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!