Recent

Author Topic: TFPGObjectList and custom sorting function  (Read 1464 times)

Чебурашка

  • Hero Member
  • *****
  • Posts: 586
  • СЛАВА УКРАЇНІ! / Slava Ukraïni!
TFPGObjectList and custom sorting function
« on: May 29, 2023, 04:11:05 pm »
Given this simple class and the related TFPGObjectList, what is the "recommended" way of implementing a custom sorting function (for example, the one shown in the comparer function below)?

Code: Pascal  [Select][+][-]
  1. unit simple;
  2.  
  3. interface
  4.  
  5. uses
  6.   classes, sysutils, fgl;
  7.  
  8. type
  9.   TItemData = class(TObject)
  10.   public
  11.     F1, F2, F3: string;
  12.    
  13.     constructor Create(A1, A2, A3: string); reintroduce;
  14.   end;
  15.  
  16. type
  17.   TItemDataList = specialize TFPGObjectList<TItemData>;
  18.  
  19. implementation
  20.  
  21. constructor TItemData.Create(A1, A2, A3: string);
  22. begin
  23.   inherited Create();
  24.  
  25.   F1 := A1; F2 := A2; F3 := A3;
  26. end;
  27.  
  28. (*
  29. function CompareItemData(Key1, Key2: Pointer): Integer;
  30. var
  31.   x1, x2: TItemData;
  32. begin
  33.   x1 := TItemData(Key1);
  34.   x2 := TItemData(Key2);
  35.  
  36.   if x1.F1 < x2.F1 then Result := -1
  37.   else if x2.F1 < x1.F2 then Result := 1
  38.   else
  39.     if x1.F2 < x2.F2 then Result := -1
  40.     else if x2.F2 < x1.F2 then Result := 1
  41.     else
  42.       if x1.F3 < x2.F3 then Result := -1
  43.       else if x2.F3 < x1.F3 then Result := 1
  44.       else
  45.         Result := 0;
  46. end;
  47. *)
  48.  
  49. end.
  50.  
FPC 3.2.0/Lazarus 2.0.10+dfsg-4+b2 on Debian 11.5
FPC 3.2.2/Lazarus 2.2.0 on Windows 10 Pro 21H2

Чебурашка

  • Hero Member
  • *****
  • Posts: 586
  • СЛАВА УКРАЇНІ! / Slava Ukraïni!
Re: TFPGObjectList and custom sorting function
« Reply #1 on: May 29, 2023, 04:23:06 pm »
I found.


Code: Pascal  [Select][+][-]
  1. function CompareItemData(const Key1, Key2: TItemData): Integer;
  2. begin
  3.  if Key1.F1 < Key2.F1 then Result := -1
  4.   else if Key2.F1 < Key1.F2 then Result := 1
  5.   else
  6.     if Key1.F2 < Key2.F2 then Result := -1
  7.     else if Key2.F2 < Key1.F2 then Result := 1
  8.     else
  9.       if Key1.F3 < Key2.F3 then Result := -1
  10.       else if Key2.F3 < Key1.F3 then Result := 1
  11.       else
  12.         Result := 0;
  13. end;
  14.  
  15. //
  16.  
  17. AFPGObjectList.Sort(@CompareItemData);
  18.  
  19.  

Sorry for the noise.
« Last Edit: May 29, 2023, 04:29:40 pm by Чебурашка »
FPC 3.2.0/Lazarus 2.0.10+dfsg-4+b2 on Debian 11.5
FPC 3.2.2/Lazarus 2.2.0 on Windows 10 Pro 21H2

Thaddy

  • Hero Member
  • *****
  • Posts: 16148
  • Censorship about opinions does not belong here.
Re: TFPGObjectList and custom sorting function
« Reply #2 on: May 29, 2023, 05:50:31 pm »
Code: Pascal  [Select][+][-]
  1. result := integer(v > 0) - integer(v < 0); // -1, 0, or +1
is my recommended way. v = keys values. And it is bloody fast.
« Last Edit: May 29, 2023, 06:12:07 pm by Thaddy »
If I smell bad code it usually is bad code and that includes my own code.

bytebites

  • Hero Member
  • *****
  • Posts: 680
Re: TFPGObjectList and custom sorting function
« Reply #3 on: May 29, 2023, 10:35:41 pm »
I found.


Code: Pascal  [Select][+][-]
  1. function CompareItemData(const Key1, Key2: TItemData): Integer;
  2. begin
  3.  if Key1.F1 < Key2.F1 then Result := -1
  4.   else if Key2.F1 < Key1.F2 then Result := 1
  5.   else
  6.     if Key1.F2 < Key2.F2 then Result := -1
  7.     else if Key2.F2 < Key1.F2 then Result := 1
  8.     else
  9.       if Key1.F3 < Key2.F3 then Result := -1
  10.       else if Key2.F3 < Key1.F3 then Result := 1
  11.       else
  12.         Result := 0;
  13. end;
  14.  
  15. //
  16.  
  17. AFPGObjectList.Sort(@CompareItemData);
  18.  
  19.  

Sorry for the noise.

Line 3:  Do you really want to compare Key2.F1 and Key1.F2?

Thaddy

  • Hero Member
  • *****
  • Posts: 16148
  • Censorship about opinions does not belong here.
Re: TFPGObjectList and custom sorting function
« Reply #4 on: May 30, 2023, 04:28:27 am »
Line 3:  Do you really want to compare Key2.F1 and Key1.F2?
He probably does, but his code is way overcomplicated as I already showed.
If I smell bad code it usually is bad code and that includes my own code.

Чебурашка

  • Hero Member
  • *****
  • Posts: 586
  • СЛАВА УКРАЇНІ! / Slava Ukraïni!
Re: TFPGObjectList and custom sorting function
« Reply #5 on: May 30, 2023, 08:32:32 am »
Line 3:  Do you really want to compare Key2.F1 and Key1.F2?

It's obviously a typo.

But problem was not the logic of the compare method, but the compare method firm, because initially I used

Code: Pascal  [Select][+][-]
  1. function CompareItemData(Key1, Key2: Pointer): Integer;
  2.  

where I should use

Code: Pascal  [Select][+][-]
  1. function CompareItemData(const Key1, Key2: TItemData): Integer;
  2.  

« Last Edit: May 30, 2023, 08:42:10 am by Чебурашка »
FPC 3.2.0/Lazarus 2.0.10+dfsg-4+b2 on Debian 11.5
FPC 3.2.2/Lazarus 2.2.0 on Windows 10 Pro 21H2

Чебурашка

  • Hero Member
  • *****
  • Posts: 586
  • СЛАВА УКРАЇНІ! / Slava Ukraïni!
Re: TFPGObjectList and custom sorting function
« Reply #6 on: May 30, 2023, 08:36:41 am »
Code: Pascal  [Select][+][-]
  1. result := integer(v > 0) - integer(v < 0); // -1, 0, or +1
is my recommended way. v = keys values. And it is bloody fast.

Thaddy could you please you explain how to use this in the context of the specific class, where fields to be compared are the various strings in the ordered way shown? I am _very_ interested in speed because in certain cases I will have to sort huge amounts of data, so any improvement will help me.
Thank you


« Last Edit: May 30, 2023, 08:40:09 am by Чебурашка »
FPC 3.2.0/Lazarus 2.0.10+dfsg-4+b2 on Debian 11.5
FPC 3.2.2/Lazarus 2.2.0 on Windows 10 Pro 21H2

jamie

  • Hero Member
  • *****
  • Posts: 6734
Re: TFPGObjectList and custom sorting function
« Reply #7 on: May 30, 2023, 01:16:20 pm »
i Belieave all you need to do is subtract one from the other, there is no need to set the actual output to -1,0 or 1,  the body code from outside the sort should be looking for  <0,0 and of course anything above 1.

 go in steps,

 Result := key1.F1-Key2.F1;

 If Result = 0 then
 result := key1.F2-Key2.F2;

 If result = 0 then......

 etc ..

I think you get what I am talking about.
« Last Edit: May 30, 2023, 01:18:56 pm by jamie »
The only true wisdom is knowing you know nothing

Чебурашка

  • Hero Member
  • *****
  • Posts: 586
  • СЛАВА УКРАЇНІ! / Slava Ukraïni!
Re: TFPGObjectList and custom sorting function
« Reply #8 on: May 30, 2023, 01:21:31 pm »
i Belieave all you need to do is subtract one from the other

In my example the fields are strings, is subtracting strings possible?

Anyway thanks ta everybody, I probably missed to explain that my problem was not the compare function logic, but its firm. I was getting compile error before turning it in the correct form.
« Last Edit: May 30, 2023, 01:23:09 pm by Чебурашка »
FPC 3.2.0/Lazarus 2.0.10+dfsg-4+b2 on Debian 11.5
FPC 3.2.2/Lazarus 2.2.0 on Windows 10 Pro 21H2

jamie

  • Hero Member
  • *****
  • Posts: 6734
Re: TFPGObjectList and custom sorting function
« Reply #9 on: May 30, 2023, 01:38:51 pm »
yes you can, but I don't know extent as to how much the fpc compiler actually does the test.

B := Integer(S1 < S2);

B being a Integer, S1 and S2 being a string.

I just assumed you were doing integers.

For Strings, you can use a already built functions in libs to generate the -1,0,1 values comparing strings.

I would need to look that up.
The only true wisdom is knowing you know nothing

 

TinyPortal © 2005-2018