TObjectList.Sort lazarus / 62-General ---------------------------------------------------------------------- Weitentaaal · 2021-12-14 08:53 Hello, was trying to Sort my ObjectList like this: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i  function CompareBTL(A, B: TBauteil):Integer; inline;begin   If (A.BtlArt = 16) and (B.BtlArt <> 16)then      Result:= 1   else      Result:= 0;end; function CompareBTLPTR(A, B: Pointer):Integer;begin   Result:= CompareBTL(TBauteil(A), TBauteil(B));end; //Call itBauteilListe.Sort(@CompareBTLPTR);   So it should put all Objects with "BTLART = 16" at the end of the List. This did not work so i saw this: https://stackoverflow.com/questions/22562873/delphi-xe-tobjectlist- sorting But i could not find this unit --> System.Generics.Defaults.TComparer what am i doing wrong ? how do assign my Compare Procedure to the Sort algorithm ? ---------------------------------------------------------------------- bytebites · 2021-12-14 12:07 Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function CompareBTLPTR(A, B: Pointer):Integer;begin   Result:= ord((TBauteilA).BtlArt = 16) or (TBauteil(B).BtlArt <> 16))end; ---------------------------------------------------------------------- Weitentaaal · 2021-12-14 12:13 Quote from: bytebites on December 14, 2021, 01:07:26 pmCode: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function CompareBTLPTR(A, B: Pointer):Integer;begin   Result:= ord((TBauteilA).BtlArt = 16) or (TBauteil(B).BtlArt <> 16))end; Sorry but how will this help me ? ---------------------------------------------------------------------- PascalDragon · 2021-12-14 12:25 Quote from: Weitentaaal on December 14, 2021, 09:53:38 amSo it should put all Objects with "BTLART = 16" at the end of the List. This did not work so i saw this: https://stackoverflow.com/questions/22562873/delphi-xe-tobjectlist- sorting Can you provide a full example, cause for me it works here? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program ttest; {$mode objfpc}{$H+} uses  SysUtils, Contnrs; type  TBauteil = class    BtlArt: LongInt;    constructor Create(aBtlArt: LongInt);    function ToString: ansistring; override;  end; { TBauteil } constructor TBauteil.Create(aBtlArt: LongInt);begin  BtlArt := aBtlArt;end; function TBauteil.ToString: ansistring;begin  Result := 'BtlArt: ' + IntToStr(BtlArt);end; function CompareBtlArt(A, B: TBauteil): Integer;begin  if (A.BtlArt = 16) and (B.BtlArt <> 16) then    Result := 1  else    Result := 0;end; function ComparePtrBtlArt(A, B: Pointer): Integer;begin  Result := CompareBtlArt(TBauteil(A), TBauteil(B));end; var  o: TObjectList;  i: LongInt;begin  o := TObjectList.Create(True);  try    o.Add(TBauteil.Create(16));    o.Add(TBauteil.Create(15));    o.Add(TBauteil.Create(16));    o.Add(TBauteil.Create(14));    o.Add(TBauteil.Create(14));     o.Sort(@ComparePtrBtlArt);     for i := 0 to o.Count - 1 do      Writeln(o[i].ToString);  finally    o.Free;  end;end. Quote from: Weitentaaal on December 14, 2021, 09:53:38 amBut i could not find this unit --> System.Generics.Defaults.TComparer It's Generics.Defaults however that will only help you for the generic TObjectList<> that's provided by Generics.Collections and not the non- generic TObjectList from Contnrs. ---------------------------------------------------------------------- Weitentaaal · 2021-12-14 12:38 I could cut it down to the Example you provided. I checked 100 times i have it the same but the only thing i got different is this : TBauteilListe = specialize TFPGObjectList; BauteilListe: TBauteilListe; Here is all i do with the List: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i //InitBauteilListe := TBauteilListe.Create(False); //Compare Functionfunction CompareBtl(A, B: TBauteil):Integer;begin   //Alle Ventilatoren ans Ende verschieben   if (A.BtlArt = 16) and (B.BtlArt <> 16) then      Result := 1   else      Result := 0;end; function ComparePtrBtl(A, B: Pointer):Integer;begin   Result:= CompareBtl(TBauteil(A), TBauteil(B));end; //working with itBauteilListe.Clear;    CurCube:= GetCube(Get_FirstCube(0));   While CurCube <> Nil do begin      BauteilListe.Add(CurCube.Bauteil);      IF CurCube.HasNextBtl() then begin         CurCube.Bauteil.NextBtl:= CurCube.NextBtl.Bauteil;      end;      IF CurCube.HasPrevBtl() then begin         CurCube.Bauteil.PrevBtl:= CurCube.PrevBtl.Bauteil;      end;      CurCube:= CurCube.NextBtl;   end;    //Ventilatoren Sollten zum Schluss gerechnet werden   BauteilListe.Sort(@ComparePtrBtl);   i do get this Compiler message: ustartup.pas(6388,36) Error: Incompatible type for arg no. 1: Got "
", expected "TFPGObjectList$1$crc3289DDC1." ---------------------------------------------------------------------- bytebites · 2021-12-14 12:51 Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i BauteilListe.Sort(@CompareBtl);  Why did you not show the type definition of the list in the first place? ---------------------------------------------------------------------- Weitentaaal · 2021-12-14 13:24 Quote from: bytebites on December 14, 2021, 01:51:13 pmCode: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i BauteilListe.Sort(@CompareBtl);  Why did you not show the type definition of the list in the first place? ustartup.pas(6388,33) Error: Incompatible type for arg no. 1: Got "
", expected "TFPGObjectList$1$crc3289DDC1." Do i have to create a type of this Function ? if so how ? Edit: if u cant help me without an example i will write the Sort algorithm myself. if so then thank you Guys very much ---------------------------------------------------------------------- bytebites · 2021-12-14 13:57 Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program foo; {$mode objfpc}{$H+} uses  Classes,  SysUtils,  fgl; type   Tbauteil = class    btlart: integer;    constructor Create(i: integer);  end;   TBauteilListe = specialize TFPGObjectList;var   BauteilListe: TBauteilListe;  i: integer;  n: Int64;    function CompareBtl(const a, b: tbauteil): integer;  var tmp1,tmp2:integer;  begin    if a.btlart=4 then tmp1:=maxint else tmp1:=a.btlart;    if b.btlart=4 then tmp2:=maxint else tmp2:=a.btlart;    result:=tmp1-tmp2;  end;   constructor Tbauteil.Create(i: integer);  begin    btlart := i;  end; begin  BauteilListe := TBauteilListe.Create;  for i := 0 to 20 do  begin    n := Random(6);    BauteilListe.Add(Tbauteil.Create(n));    writeln(n.ToString);  end;  writeln('----------');  BauteilListe.sort(@CompareBtl);  for i := 0 to 20 do    writeln(BauteilListe[i].btlart.ToString); end. ---------------------------------------------------------------------- Weitentaaal · 2021-12-15 06:43 Quote from: bytebites on December 14, 2021, 02:57:22 pmCode: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program foo; {$mode objfpc}{$H+} uses  Classes,  SysUtils,  fgl; type   Tbauteil = class    btlart: integer;    constructor Create(i: integer);  end;   TBauteilListe = specialize TFPGObjectList;var   BauteilListe: TBauteilListe;  i: integer;  n: Int64;    function CompareBtl(const a, b: tbauteil): integer;  var tmp1,tmp2:integer;  begin    if a.btlart=4 then tmp1:=maxint else tmp1:=a.btlart;    if b.btlart=4 then tmp2:=maxint else tmp2:=a.btlart;    result:=tmp1-tmp2;  end;   constructor Tbauteil.Create(i: integer);  begin    btlart := i;  end; begin  BauteilListe := TBauteilListe.Create;  for i := 0 to 20 do  begin    n := Random(6);    BauteilListe.Add(Tbauteil.Create(n));    writeln(n.ToString);  end;  writeln('----------');  BauteilListe.sort(@CompareBtl);  for i := 0 to 20 do    writeln(BauteilListe[i].btlart.ToString); end. Hi again, It's working now, thank you both for your effort The Problem was this: I had to change this:  function CompareBtl(a, b: tbauteil): integer; to this:  function CompareBtl(const a, b: tbauteil): integer; would be nice if someone could tell me why its necessary to do so. Wiki says: "Declaring a parameter as const allows the compiler the possibility to do optimizations it couldn't do otherwise, such as passing by reference while retaining the semantics of passing by value. A const parameter cannot be passed to another function or procedure that requires a variable parameter." I don't really get what is ment by "do the optimizations" ---------------------------------------------------------------------- Handoko · 2021-12-15 07:19 I don't know much about the generic/specialize things but I can explain why using const parameter can be good for some cases. Look at this example: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function IsStringEmpty1(aString: string): Boolean;begin  Result := aString.Length <= 0;end; function IsStringEmpty2(const aString: string): Boolean;begin  Result := aString.Length <= 0;end; procedure TForm1.Button1Click(Sender: TObject);var  Data: string;begin  Data := 'Sample data';  if IsStringEmpty1(Data) then ShowMessage('It''s empty');  if IsStringEmpty2(Data) then ShowMessage('It''s empty');end; The line #16 and #17 will give you the same result. In the example above you won't feel any performance difference but if the Data is a very long string and performance is important, IsStringEmpty2 will run much faster. What will happen when the computer executes the line #16 ? The system will reserve some space from unused memory, copy the content of Data to the newly allocated memory and then call the function line #1 and pass the location of the newly allocated memory to it. Now, look at the line #6. By making the parameter as a const parameter then there will a big difference. When the computer executes the line #17, it simply calls the function and passes the location of Data to it. Perhaps you will ask, why not making all parameters as const parameters by default? That is a long story. In short, making a parameter as a const parameter does not always mean better or faster. But usually you will get better optimized code by making string parameters as const parameters. ---------------------------------------------------------------------- PascalDragon · 2021-12-15 08:01 Quote from: Weitentaaal on December 14, 2021, 01:38:01 pmI could cut it down to the Example you provided. I checked 100 times i have it the same but the only thing i got different is this : TBauteilListe = specialize TFPGObjectList; BauteilListe: TBauteilListe; Next time please mention that right away, cause I was working on the assumption that you use Contnrs.TObjectList and not FGL.TFPGObjectList<> which - while similar - do have slightly different usages... Quote from: Weitentaaal on December 15, 2021, 07:43:58 amIt's working now, thank you both for your effort The Problem was this: I had to change this:  function CompareBtl(a, b: tbauteil): integer; to this:  function CompareBtl(const a, b: tbauteil): integer; would be nice if someone could tell me why its necessary to do so. It's necessary, because the compiler explicitely told you so (emphasis mine): Quote from: Weitentaaal on December 14, 2021, 02:24:11 pmustartup.pas(6388,33) Error: Incompatible type for arg no. 1: Got "
", expected "TFPGObjectList$1$crc3289DDC1." The compare function of TFPGObjectList<> is declared as TCompareFunc = function(const Item1, Item2: T): Integer; and functions assigned to function variables must be equal in their signature (which the compiler assures as you can see) as otherwise things can go terribly wrong. ---------------------------------------------------------------------- Weitentaaal · 2021-12-15 08:08 Thank you both for the Explanations, they were very helpful understanding the const-parameter better  "Next time please mention that right away", i am very sorry, please forgive me