TFPGObjectList -> Sort() Funktion, Typdefinition Funktionstyp [GELÖST]

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Benutzeravatar
Zvoni
Beiträge: 363
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz 2.2.2 FPC 3.2.2)
CPU-Target: 32Bit
Wohnort: BW

Re: TFPGObjectList -> Sort() Funktion, Typdefinition Funktionstyp

Beitrag von Zvoni »

Und statt zwei Vergleichsmethoden hätte ich ein Privates Feld FAscending:Integer in die Liste gehängt, die Sort-Methode einen Overload hinzu, welches zwei Argumente bekommt (Adresse der Vergleichsfunktion, und ein Boolean-Flag ob Auf- oder Absteigend)

Dann braucht man nur eine Compare-Methode
Aircode...

Code: Alles auswählen

Procedure TMyList.Sort(ACompareFunc:TCompareFunction; Const Ascending:Boolean);
Being
  If Ascending Then FAscending:=-1 Else FAscending:=1;
  Inherited Sort;
End;

function CompareFunc(const Item1,tem2: TmyType): LongInt; Register;  
begin  
  if TmyType(Item1).comparefield < TmyType(item2).comparefield then Result := -1*FAscending else
  if TmyType(Item1).comparefield > myType(item2).comparefield then Result := 1*FAscending else Result := 0;
end;
Aufruf dann mit

Code: Alles auswählen

Sort(@CompareFunc,True)  //Aufsteigend
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

multiplatform-coder
Beiträge: 59
Registriert: Do 20. Apr 2023, 18:25

Re: TFPGObjectList -> Sort() Funktion, Typdefinition Funktionstyp

Beitrag von multiplatform-coder »

OK, ich habe nun mal das folgende Testbeispiel erzeugt und erhalte beim Compilieren denselben Fehler vom Compiler gemeldet.

Den hier:

Testproject1.lpr(70,43) Error: Incompatible type for arg no. 1: Got "<address of function(Pointer;Pointer):LongInt;Register>", expected "TFPGObjectList$1$crcE0B4E8C7.<procedure variable type of function(const TData;const TData):LongInt;Register>"

Und hier ist nun mein Code:

Code: Alles auswählen

program Testproject1;

{$Apptype console}
uses
  Classes, SysUtils, fgl;

type
  TData = class(TComponent)
  private
     FFirstName: string;
     FFamilyName: String;
  public
     constructor Create(aFirst, aLast: String);

     property FirstName: String read FFirstName;
     Property FamilyName: String read FFamilyName;

  end;

  TDataList = specialize TFPGObjectList<TData>;
  TSortedItems = class (TDataList)
  private
     FAscending: Boolean;
  public
     function Add(afirst,alast: String): integer;  
     procedure SetAscanding(AValue: Boolean);
     procedure GetFrom(AList: TDataList; aItems: TSortedItems);      //Anstatt Assign //  var aItems andert nichts an der jetzt immer noch fehlenden Ausgabe meiner Daten
     procedure GiveSorted(var asorted: TSortedItems);

     property Ascending: Boolean read FAscending write FAscending;
  end;



function CompareAscending(const Item1,Item2: TData): Integer;   //aufsteigend
begin
  if TData(Item1).FirstName < TData(Item2).FirstName
     then Result := 1 else
  if TData(Item1).FirstName > TData(Item2).FirstName
     then Result := -1 else Result := 0;
end;

function CompareDescending(const Item1,Item2: TData): Integer;   //absteigend
begin
  if TData(Item1).FirstName < TData(Item2).FirstName
     then Result := -1 else
  if TData(Item1).FirstName > TData(Item2).FirstName
     then Result := 1 else Result := 0;
end;

function TSortedItems.Add(afirst,alast: String): integer;
begin
  Result := inherited Add (TData.Create(firstname,lastname));
  Result := inherited Add(aData);
end;

procedure TSortedItems.SetAscanding(AValue: Boolean);
begin
  if FAscending <> AValue then
  begin
    FAscending := AValue;
  end;
end;

procedure TSortedItems.GetFrom(AList: TDataList; aItems: TSortedItems);
var ix: Integer;
begin
  ix := 0;
  if Assigned(AList) then
  while ix < AList.Count do
  begin
    aItems.Add(TData(AList.Items[ix]),FirstName; TData(AList.Items[ix]).FamilyName);  //hier sollen die Items der Datenlist in die sortierte Liste übertragen werden, bzw. in die anschließend zu sortierende
  
    //die Inhalte der Vergleichsfelder sind in von TComponent
    //abgeleiteten Klassen enthalten
  
    inc(ix);
  end;
  
  if Ascending then aItems.Sort(@CompareAscending) else Sort(@CompareDescending);  
  
  //hier soll die sortierte Liste die Sortierung realisieren
  
end;

procedure TSortedItems.GiveSorted(var asorted: TSortedItems);
var ix: Integer;
begin
    asorted := self;

{ Was ich hier machen wollte wird nun bereits in GetFrom() hoffentlich besser erledigt
 
  ix := 0;
  while ix < count do
  begin
    asorted.Add(TData(Items[ix]));   //hier wollte ich sortierten Items ursprünglich ausgeben, habe aber inzwischen GetFrom Metode geändert.
    inc(ix);
  end;
    if Ascending then Sort(@CompareAscending) else Sort(@CompareDescending);
    }
    //hier sollen die sortirten Items nach draußen ausgegeben werden
end;


end.

var
  Data: TData;
  DataList: TDataList;
  SortedList: TSortedItems;

begin
  DataList := TDataList.Create;
  SortedList := TSortedItems.Create;
  SortedList.Ascending := true;
  DataList.Add('Kurt','Mieth');
  
  DataList.Add('Karl','Lauterbach');
  
  DataList.Add('Ursula','Handrick');
 
  DataList.Add('Sabine','Wehner');
 
  DataList.Add('Andrea','Dachselt');
 
  DataList.Add('Ulrike','Schneider');
 
  DataList.Add('Dorothee','Konradi');
 
  DataList.Add('Lutz','Schäfer');
  
  DataList.Add('Carola Flechner','');
  
  SortedList.GetFrom(DataList,SortedList);
  
  writeln(TData(SortedList[0]).FirstName,TData(SortedList[0]).FamilyName);
  writeln(TData(SortedList[1]).FirstName,TData(SortedList[1]).FamilyName);
  writeln(TData(SortedList[2]).FirstName,TData(SortedList[2]).FamilyName);
  writeln(TData(SortedList[3]).FirstName,TData(SortedList[3]).FamilyName);
  writeln(TData(SortedList[4]).FirstName,TData(SortedList[4]).FamilyName);
  writeln(TData(SortedList[5]).FirstName,TData(SortedList[5]).FamilyName);
  writeln(TData(SortedList[6]).FirstName,TData(SortedList[6]).FamilyName);
  writeln(TData(SortedList[7]).FirstName,TData(SortedList[7]).FamilyName);
  writeln(TData(SortedList[8]).FirstName,TData(SortedList[8]).FamilyName);
  writeln('Zurück mit <<ENTER>>...');
end.
       
Zuletzt geändert von multiplatform-coder am Do 17. Apr 2025, 20:45, insgesamt 6-mal geändert.

Benutzeravatar
theo
Beiträge: 10856
Registriert: Mo 11. Sep 2006, 19:01

Re: TFPGObjectList -> Sort() Funktion, Typdefinition Funktionstyp

Beitrag von theo »

Code: Alles auswählen

function CompareAscending(const Item1,Item2: TData): Integer;   //aufsteigend 
etc.

Benutzeravatar
Zvoni
Beiträge: 363
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz 2.2.2 FPC 3.2.2)
CPU-Target: 32Bit
Wohnort: BW

Re: TFPGObjectList -> Sort() Funktion, Typdefinition Funktionstyp

Beitrag von Zvoni »

Wie oft muss theo eigentlich noch erwähnen, dass du keine POINTER verwenden kannst?
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

Benutzeravatar
theo
Beiträge: 10856
Registriert: Mo 11. Sep 2006, 19:01

Re: TFPGObjectList -> Sort() Funktion, Typdefinition Funktionstyp

Beitrag von theo »

Es ist auch das "const".

Code: Alles auswählen

TCompareFunc = function(const Item1, Item2: T): Integer;       
So ist das definiert in der Unit fgl und so soll man es machen.

multiplatform-coder
Beiträge: 59
Registriert: Do 20. Apr 2023, 18:25

Re: TFPGObjectList -> Sort() Funktion, Typdefinition Funktionstyp

Beitrag von multiplatform-coder »

Ok danke soweit, das "Const" hat in der Verleichsfunktion gefehlt. Hetzt wird das @ Zeichen auch als Zeichen für Funktionszeiger akzeptiert, aber ich erhalte keije Ausgabe. Weder unsortiert noch sortiert. Meine Liste vom Typ TSortedItems soll die sortierte LIste ausgeben, deshalb die Methoden GiveSorted() bzw. GetFrom(). Was muss ich da noch anders machen?

Ich müsste doch wenigstens erst mal die unsortierte Liste ausgegeben kriegen.

Benutzeravatar
Zvoni
Beiträge: 363
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz 2.2.2 FPC 3.2.2)
CPU-Target: 32Bit
Wohnort: BW

Re: TFPGObjectList -> Sort() Funktion, Typdefinition Funktionstyp

Beitrag von Zvoni »

Dir ist klar, dass du jedesmal diesselbe Variable "Data" verwendest, um eine NEUE Instanz von TData zu Createn?
.....bin mir sogar sicher, so wie das jetzt ist, leckt das wie ein Sieb......
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

multiplatform-coder
Beiträge: 59
Registriert: Do 20. Apr 2023, 18:25

Re: TFPGObjectList -> Sort() Funktion, Typdefinition Funktionstyp

Beitrag von multiplatform-coder »

Kann ich die Instanzvariable nicht nach meinem DataList.Add(Data) neu belegen?

Und warum erhalte ich immer noch keine Ausgabe? Ich habe den Quellcode oben aktualisiert.

Benutzeravatar
Zvoni
Beiträge: 363
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz 2.2.2 FPC 3.2.2)
CPU-Target: 32Bit
Wohnort: BW

Re: TFPGObjectList -> Sort() Funktion, Typdefinition Funktionstyp

Beitrag von Zvoni »

multiplatform-coder hat geschrieben: Do 17. Apr 2025, 13:17 Kann ich die Instanzvariable nicht nach meinem DataList.Add(Data) neu belegen?

Und warum erhalte ich immer noch keine Ausgabe? Ich habe den Quellcode oben aktualisiert.
Die "Variable" einer Klassen-Instanz ist ein Zeiger. Wenn du diese recyclest, überschreibst du das, was an der Adresse steht bzw. das vorherige fliegt ins Nirvana, egal wo es "gespeichert" ist....
Statt ner Klasse, würde ich mir eher Advanced Records anschauen
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

paweld
Beiträge: 85
Registriert: So 11. Jun 2023, 16:01
OS, Lazarus, FPC: Lazarus trunk, FPC fixes

Re: TFPGObjectList -> Sort() Funktion, Typdefinition Funktionstyp

Beitrag von paweld »

Zvoni hat geschrieben: Do 17. Apr 2025, 12:52 Dir ist klar, dass du jedesmal diesselbe Variable "Data" verwendest, um eine NEUE Instanz von TData zu Createn?
.....bin mir sogar sicher, so wie das jetzt ist, leckt das wie ein Sieb......
Das stört Sie überhaupt nicht, solange Sie am Ende die Liste freigeben, zu der Sie all diese erstellten Klassen hinzufügen - standardmäßig hat TFPGObjectList die Eigenschaft FreeObjects auf True gesetzt.

Natürlich gibt das @multiplatform-coder die Listen nicht frei, so dass es zu Speicherlecks kommt.
Grüße / Pozdrawiam
paweld

multiplatform-coder
Beiträge: 59
Registriert: Do 20. Apr 2023, 18:25

Re: TFPGObjectList -> Sort() Funktion, Typdefinition Funktionstyp

Beitrag von multiplatform-coder »

Ok, Danke, da mache ich das erst mal.

multiplatform-coder
Beiträge: 59
Registriert: Do 20. Apr 2023, 18:25

Re: TFPGObjectList -> Sort() Funktion, Typdefinition Funktionstyp

Beitrag von multiplatform-coder »

Funktioniert denn der Advanced Record auch mit den Generischen Listen?

Habe den zwar noch nicht verwendet, funktioniert laut Doku aber wie ein Obkekt oder eine Klasse. man kann Methoden hinzufügen, aber nichts vererben,
Sollte dann aber wie eine Klasse funktionieren und genau so referenziert werden. Ist das richtig verstanden?

Mein Beispiel habe ich jetzt wie folgt geändert, bekomme aber immer noch keine Ausgabe. Ich beziehe mich daei auf example6.lpr von hier:
https://github.com/silvercoder70/code-e ... ample6.lpr

Code: Alles auswählen

  { TData }

  TData = class(TComponent)
  private
     FFirstName: string;
     FFamilyName: String;
  public
     constructor Create(aFirst, aLast: String);

     property FirstName: String read FFirstName;
     Property FamilyName: String read FFamilyName;

  end;

  TDataList = specialize TFPGList<TData>;
  TDataListEnumerator = specialize TFPGListEnumerator<TData>;


var
  Data: TData;
  DataList: TDataList;
  EnumList: TDataListEnumerator;
  SortedList: TSortedItems;


begin
  DataList := TDataList.Create;

  DataList.Add(TData.Create('Kurt','Mieth'));
  DataList.Add(TData.Create('Karl','Lauterbach'));
  DataList.Add(TData.Create('Ursula','Handrick'));
  DataList.Add(TData.Create('Sabine','Wehner'));
  DataList.Add(TData.Create('Andrea','Dachselt'));
  DataList.Add(TData.Create('Ulrike','Schneider'));
  DataList.Add(TData.Create('Dorothee','Konradi'));
  DataList.Add(TData.Create('Lutz','Schäfer'));
  DataList.Add(TData.Create('Carola', 'Flechner'));

  DataList.Sort(@CompareAscending); nach example6.lpr im obigen Link

  ENumList := DataList.GetEnumerator;  //nach example6.lpr im obigen Link  Enumerator zuweisen
  while EnumList.MoveNext do   //nach example6.lpr im obigen Link prüfen ob noch weitere Eintäge da sind
  begin
    Data := EnumList.Current;  //nach example6.lpr  aktuellen Eintrag holen
    writeln(Data.FirstName,'    ',Data.FamilyName);  //nach example6.lpr  aktuellen Eintrag ausgeben
  end;
  
  DataList.Free;   //Liste frei geben
 
  writeln('Zurück mit <<ENTER>>...');
  
 
end.


Warum erhalte ich nun immer noch keine Ausgabe?

Ich kann mir nicht vorstellen wieso bei einem Advanced Record die Ausgabe auf einmal funktionieren sollte.

Ich muss dann Advaced Records verlangrn duch {$modeswitch advancedrecords} und lt. Doku auch voher noch {$mode objfpc} und danch die advancedrecords einstellen.

Mein Advanced Record sieht daher so aus:

Im Projekt {$mode objfpc}{$H+}{$modeswitch advancedrecords}

type

TDataRecord = record
FFirstName: string;
FFamilyName: String;
function FirstName: String;
function FamilyName: String;
end;

function TDataRecord.FirstName: String;
begin
Result := FFirstName;
end;

function TDataRecord FamilyName: String;
begin
Result := FFamilyName;
end;

Mein Quellcode benutzt aber noch meinen alten TData Typ.


.

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2805
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: TFPGObjectList -> Sort() Funktion, Typdefinition Funktionstyp

Beitrag von m.fuchs »

multiplatform-coder hat geschrieben: Fr 18. Apr 2025, 21:14 Warum erhalte ich nun immer noch keine Ausgabe?
Keine Ahnung, ich hab deinen Code genommen und mit dem CompareAscending von oben ergänzt, den Constructor angelegt und "SortedList: TSortedItems;" entfertn. Damit bekomme ich eine Ausgabe. Allerdings eine falsch sortierte, weil dein CompareAscending flasch programmiert ist.

Hier ist mal eine aufgeräumte, lauffähige Version mit ein paar Anmerkungen:

Code: Alles auswählen

program TestProject;
{$MODE ObjFPC}
{$H+}

uses
  Classes, Fgl;

type
  TData = class(TObject)  // Warum TComponent?
    private
      FFirstName: string;
      FFamilyName: String;
   public
    constructor Create(aFirst, aLast: String);
    property FirstName: String read FFirstName;
    Property FamilyName: String read FFamilyName;
 end;

 TDataList = specialize TFPGObjectList<TData>; // Hab hier mal eine TFPGObjectList genommen,
                                               // sind ja Objekte die da reinkommen

constructor TData.Create(aFirst, aLast: String);
begin
  FFirstName := aFirst;
  FFamilyName := aLast;
end;

function CompareAscending(const Item1,Item2: TData): Integer;
begin
  // unnötige Casts entfernt
  // die Vergleichsoperatoren waren genau falsch herum
  if Item1.FirstName > Item2.FirstName then
    Result := 1
  else if Item1.FirstName < Item2.FirstName then
    Result := -1
  else
    Result := 0;
end;

var
 Data: TData;
 DataList: TDataList;

begin
  DataList := TDataList.Create;
  DataList.Add(TData.Create('Kurt','Mieth'));
  DataList.Add(TData.Create('Karl','Lauterbach'));
  DataList.Add(TData.Create('Ursula','Handrick'));
  DataList.Add(TData.Create('Sabine','Wehner'));
  DataList.Add(TData.Create('Andrea','Dachselt'));
  DataList.Add(TData.Create('Ulrike','Schneider'));
  DataList.Add(TData.Create('Dorothee','Konradi'));
  DataList.Add(TData.Create('Lutz','Schäfer'));
  DataList.Add(TData.Create('Carola', 'Flechner'));
  DataList.Sort(@CompareAscending);

  // einfacherer Enumerator-Zugriff
  for Data in DataList do begin
    WriteLn(Data.FirstName, '    ', Data.FamilyName);
  end;

  DataList.Free;
end.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

multiplatform-coder
Beiträge: 59
Registriert: Do 20. Apr 2023, 18:25

Re: TFPGObjectList -> Sort() Funktion, Typdefinition Funktionstyp

Beitrag von multiplatform-coder »

Danke @m.fuchs wie verrückt. So funktioniert es jetzt wirklich. Ich werde mir das Beispiel in meiner Codebasis abspeichern zum Nachschauen für später.

Das "Data in Datalist" muss ich mir merken, da hätte ich wohl mit dem Enumerator noch lange rum gebastelt. Danke noch mal! :?

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2805
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: TFPGObjectList -> Sort() Funktion, Typdefinition Funktionstyp

Beitrag von m.fuchs »

multiplatform-coder hat geschrieben: Sa 19. Apr 2025, 10:09 Das "Data in Datalist" muss ich mir merken, da hätte ich wohl mit dem Enumerator noch lange rum gebastelt. Danke noch mal! :?
Das mit dem Enumerator funktioniert ja auch, das andere ist nur eine Vereinfachung.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Antworten