Bookstore

 Computer Math and Games in Pascal (preview) Lazarus Handbook

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

Чебурашка

• Sr. Member
• Posts: 453
• СЛАВА УКРАЇНІ! / 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

Чебурашка

• Sr. Member
• Posts: 453
• СЛАВА УКРАЇНІ! / 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

• Hero Member
• Posts: 13212
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 »
I actually get compliments for being rude... (well, Dutch, but that is the same)

bytebites

• Hero Member
• Posts: 573
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?

• Hero Member
• Posts: 13212
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.
I actually get compliments for being rude... (well, Dutch, but that is the same)

Чебурашка

• Sr. Member
• Posts: 453
• СЛАВА УКРАЇНІ! / 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

Чебурашка

• Sr. Member
• Posts: 453
• СЛАВА УКРАЇНІ! / 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: 5695
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

Чебурашка

• Sr. Member
• Posts: 453
• СЛАВА УКРАЇНІ! / 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: 5695
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