[gelöst]Gibt es in FPC eine IntegerList?

Rund um die LCL und andere Komponenten
hubblec4
Beiträge: 341
Registriert: Sa 25. Jan 2014, 17:50

[gelöst]Gibt es in FPC eine IntegerList?

Beitrag von hubblec4 »

Hallo

Ich habe dazu ein wenig Goggle befragt, aber so richtig fündig bin ich nicht geworden.

Daher hier mal die Frage ob ich so eine IntegerList irgendwo in FPC finde.

Warum soll es eine IntegerList sein und nicht ein dynamisches Array of Integer:
Ich benötige eine Sortfunktion (wie bei TStringList). Integer müssten einfügbar sein (Insert und nicht nur Add), ebenso das löschen.
Das alles geht mit einer List besser als mit einem Array, denke ich mal.

LG
hubble
Zuletzt geändert von hubblec4 am Mi 12. Sep 2018, 15:11, insgesamt 1-mal geändert.

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Gibt es in FPC eine IntegerList?

Beitrag von wp_xyz »

In Lazarus trunk gibt es im Package LazUtils eine Unit "IntegerList" mit

Code: Alles auswählen

type
  TByteList = class(specialize TFPGList<Byte>)
 
  TWordList = class(specialize TFPGList<Word>)
 
  TCardinalList = class(specialize TFPGList<Cardinal>)
 
  TIntegerList = class(specialize TFPGList<Integer>)
 
  TInt64List = class(specialize TFPGList<Int64>)
 

hubblec4
Beiträge: 341
Registriert: Sa 25. Jan 2014, 17:50

Re: Gibt es in FPC eine IntegerList?

Beitrag von hubblec4 »

Die Unit LazUtils hatte ich auch mal getetstet, da kam aber nichts mit IntegerList.
Hatte dann gelesen das die in 1.8.2 wieder entfernt wurde.
Warum?

Wenn es in Lazarus-Trunk drinne ist, kommt die Unit auch wieder in die normale Lazarus Variante?

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Gibt es in FPC eine IntegerList?

Beitrag von Warf »

Code: Alles auswählen

uses
fgl;
...
type
TIntegeList = specialize TFPGList<Integer>;

Ist das einfachste

hubblec4
Beiträge: 341
Registriert: Sa 25. Jan 2014, 17:50

Re: Gibt es in FPC eine IntegerList?

Beitrag von hubblec4 »

Habe es eben mal so eingegeben und sieht gut aus. Danke für den Tipp.

hubblec4
Beiträge: 341
Registriert: Sa 25. Jan 2014, 17:50

Re: Gibt es in FPC eine IntegerList?

Beitrag von hubblec4 »

Für so eine TIntegerList gibt es bei der procedure Sort nun einen Parameter

Code: Alles auswählen

Compare: TFPSListCompareFunc


Da muss jetzt eine Funtion als Paramater übergeben werden, und welche und woher nehme ich diese um die Zahlen von klein nach groß zu sortieren?

hubble

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Gibt es in FPC eine IntegerList?

Beitrag von Socke »

Du kannst in Lazarus mit CTRL+Mausklick zur Deklaration springen, dann findest du folgende Deklaration:

Code: Alles auswählen

    type
      TCompareFunc = function(const Item1, Item2: T): Integer;

Da diese Deklaration Bestandteil der generischen Klasse ist, sind die Parameter Itme1 und Item2 vom jeweiligen Listentyp.

Code: Alles auswählen

type
  TMyIntegerList = specialize TFPGList<Integer>;
 
function SortMyList(const Item1, Item2: Integer): Integer;
begin
  Result := Item2 - Item1;
end;
 
var
  l: TMyIntegerList;
begin
  l := TMyIntegerList.Create;
  l.Sort(@SortMyList);
  l.Destroy;
end.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

hubblec4
Beiträge: 341
Registriert: Sa 25. Jan 2014, 17:50

Re: Gibt es in FPC eine IntegerList?

Beitrag von hubblec4 »

OK, danke für die Erklärung.
Das Result der Function SortMyList kann ich dann so verändern das ab- oder aufsteigend sortiert werden soll?


EDIT:

Sollte ich mal eine Liste für Floats benötigen, dann muss die SortMyList function so aussehen?

Code: Alles auswählen

 
function SortMyList(const Item1, Item2: Extended): Extended;
begin
  Result := Item2 - Item1;
end;
 

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Gibt es in FPC eine IntegerList?

Beitrag von Warf »

hubblec4 hat geschrieben:OK, danke für die Erklärung.
Das Result der Function SortMyList kann ich dann so verändern das ab- oder aufsteigend sortiert werden soll?


EDIT:

Sollte ich mal eine Liste für Floats benötigen, dann muss die SortMyList function so aussehen?

Code: Alles auswählen

 
function SortMyList(const Item1, Item2: Extended): Extended;
begin
  Result := Item2 - Item1;
end;
 


Nein das Ergebnis der Funktion muss ein int sein sodass er 0 ist wenn sie gleich sind und < 0 wenn item 1 geößer ist und > 0 wenn item 2 geößer ist.

Frank Ranis
Beiträge: 201
Registriert: Do 24. Jan 2013, 21:22

Re: Gibt es in FPC eine IntegerList?

Beitrag von Frank Ranis »

Hallo ,

ich finde das Thema auch interessant und habe mal rumprobiert.

Erst mit int64 und dann mit extended.

Das aufsteigend sortieren funzt bei int64 und auch bei extended super.

Bei absteigend und extended hat die Sort-Routine aber Probleme mit den Nachkommastellen .

Kann man das irgendwie in den Griff bekommen ?

Code: Alles auswählen

unit Unit1;
 
{$mode objfpc}{$H+}
 
interface
 
uses
 Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
 fgl;
 
type
 
 { TForm1 }
 
 TForm1 = class(TForm)
  Button1: TButton;
  Button2: TButton;
  Memo1: TMemo;
  RadioButton1: TRadioButton;
  RadioButton2: TRadioButton;
  procedure Button1Click(Sender: TObject);
  procedure Button2Click(Sender: TObject);
 private
 
 public
 
 end;
 
 Tint64List = specialize TFPGList<int64>;
 TextendedList = specialize TFPGList<extended>;
 
var
 Form1: TForm1;
 i64_list:Tint64List;
 extended_list:TextendedList;
 
 // Up Down int64-Sortier-Funktionen
 function SortMyList_int64_up(const Item1, Item2: int64): longint;
 function SortMyList_int64_down(const Item1, Item2: int64): longint;
 // Up Down extended-Sortier-Funktionen
 function SortMyList_extended_up(const Item1, Item2: extended): longint;
 function SortMyList_extended_down(const Item1, Item2: extended): longint;
 
implementation
 
{$R *.lfm}
 
{ TForm1 }
 
// Int64 Sort-Funktionen
function SortMyList_int64_up(const Item1, Item2: int64): longint;
begin
  Result := Item1 - Item2;
end;
function SortMyList_int64_down(const Item1, Item2: int64): longint;
begin
  Result := Item2 - Item1;
end;
 
// Extended Sort-Funktionen
function SortMyList_extended_up(const Item1, Item2: extended): longint;
begin
 Result := round(Item1 - Item2);
end;
function SortMyList_extended_down(const Item1, Item2: extended): longint;
begin
 Result := round(Item2 - Item1);
end;
 
// Int64 - Beispiel
procedure TForm1.Button1Click(Sender: TObject);
var i:integer;
    iz:int64;
begin
 i64_list:=Tint64List.Create;
 i64_list.Clear;
 i64_list.Add(5);
 i64_list.Add(82898797);
 i64_list.Add(995);
 i64_list.Add(115);
 i64_list.Add(445);
 i64_list.Add(577777);
 i64_list.Add(55555);
 Memo1.Clear;
 
 memo1.lines.add('Orginal Eingabedaten');
 for i:=0 to i64_list.Count-1 do
  begin
   iz:=i64_list[i];
   memo1.lines.add(floattostr(iz));
  end;
 
 if radiobutton1.Checked
  then i64_list.Sort(@SortMyList_int64_up);
 if radiobutton2.Checked
  then i64_list.Sort(@SortMyList_int64_down);
 
 memo1.lines.add('');
 memo1.lines.add('Sortiert');
 for i:=0 to i64_list.Count-1 do
  begin
   iz:=i64_list[i];
   memo1.lines.add(floattostr(iz));
  end;
 i64_list.free;
end;
 
// Extended - Beispiel
procedure TForm1.Button2Click(Sender: TObject);
var i:integer;
    iz:extended;
begin
 extended_list:=TextendedList.Create;
 extended_list.Clear;
 extended_list.Add(5.33);
 extended_list.Add(82898797.01);
 extended_list.Add(995.99000);
 extended_list.Add(995.98999);
 extended_list.Add(445.45);
 extended_list.Add(577777.001);
 extended_list.Add(55555.999);
 Memo1.Clear;
 
 memo1.lines.add('Orginal Eingabedaten');
 for i:=0 to extended_list.Count-1 do
  begin
   iz:=extended_list[i];
   memo1.lines.add(floattostr(iz));
  end;
 
 if radiobutton1.Checked
  then extended_list.Sort(@SortMyList_extended_up);
 if radiobutton2.Checked
  then extended_list.Sort(@SortMyList_extended_down);
 
 memo1.lines.add('');
 memo1.lines.add('Sortiert');
 for i:=0 to extended_list.Count-1 do
  begin
   iz:=extended_list[i];
   memo1.lines.add(floattostr(iz));
  end;
 extended_list.free;
end;
 
end.
 

Gruß

Frank
Dateianhänge
LAZ_specialize_TFPGList.zip
(127.09 KiB) 72-mal heruntergeladen
www.flz-vortex.de

hubblec4
Beiträge: 341
Registriert: Sa 25. Jan 2014, 17:50

Re: Gibt es in FPC eine IntegerList?

Beitrag von hubblec4 »

Frank Ranis hat geschrieben:Bei absteigend und extended hat die Sort-Routine aber Probleme mit den Nachkommastellen .

Kann man das irgendwie in den Griff bekommen ?



Wenn ich so recht darüber nachdenke dann sehe ich da auch ein kleines Problem.

Durch die Function round() wird man örfters auf falsche Sortierungen stoßen.

Item1:=0.0005
Item2:=0.0004
Result:= item1 - item2 = 0.0001 -> gerundet = 0 -> kein Verschieben.
Das ist dann falsch da ja 0.0004 kleiner ist und verschoben werden müsste.

Ich würde da als ersten Anstaz die Float Werte "Hoch-Integern" (weis nicht wie ich es anders nennen soll)

Code: Alles auswählen

 
// Extended Sort-Funktionen
function SortMyList_extended_up(const Item1, Item2: extended): longint;
const IntUp: Integer=1000000000; Nanosekunden Präzession
begin
 Result := round(Item1*IntUp - Item2*IntUp);
end;
 

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Gibt es in FPC eine IntegerList?

Beitrag von Socke »

Um Rundungsfehler zu vermeiden muss der Nachkommateil ebenfalls beachtet werden.
Ich würde die Zahlen hier einfach vergleichen:

Code: Alles auswählen

if Item1 < Item2 then
  Result := -1
else if Item1 > Item2 then
  Result := 1
else // Item 1 = Item2
  Result := 0;

hubblec4 hat geschrieben:Ich würde da als ersten Anstaz die Float Werte "Hoch-Integern" (weis nicht wie ich es anders nennen soll)

Damit kommst du ganz einfach aus dem Gültigkeitsbereich hinaus oder verfälscht die Ergebnisse - Fließkommazahlen sind immer ungenau!
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

hubblec4
Beiträge: 341
Registriert: Sa 25. Jan 2014, 17:50

Re: Gibt es in FPC eine IntegerList?

Beitrag von hubblec4 »

Da hast du recht Socke. Deine Lösung gefällt mir auch besser und ich finde, dass diese art der Abfrage für Integer also auch für Floats funktioniert.

Schade eigentlich das diese

Code: Alles auswählen

Compare: TFPSListCompareFunc

zwei Integer als Parameter erwartet in der Function erwartet. Wär es nicht besser das wären gleich Floats? Denn ein Integer ist ja auch ein Float, oder?


EDIT: eine kleine Bemerkung zu den Floats habe ich da noch.

wenn man mit

Code: Alles auswählen

 if item1 = item2 then

die beiden Floats vergleicht ist bei mir folgendes aufgetreten.

item1 = 0
item2 wurde durch ein paar berechnungen in meinem Programm ermittelt und sollte auch 0 ergeben, was ja eigentlich auch der Fall ist.
Nur wird für item2 die 0 so dargestellt 0.0+10E-1 oder so, weis jetzt gerade nicht ganz genau.
Auf jedenfall sind beide Items NICHT gleich was dann dazu führte das falsche weitere prozeduren ausgelöst wurden, daher habe ich dann alles soweit auf int64 umgestellt.

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Gibt es in FPC eine IntegerList?

Beitrag von Warf »

Für floats könnte man nicht einfach die von einander abziehen und dann vor dem runden mit dem exponenten multiplizieren (also wenn 1,x *2^-n rauskommt einfach mit 2^n multiplizieren) müsste durch die floatingpoint Darstellung doch eigentlich funktionieren?
Wenn nicht exakt 0 rauskommt müsste danach dann ja 1 oder -1 rauskommen

hubblec4
Beiträge: 341
Registriert: Sa 25. Jan 2014, 17:50

Re: Gibt es in FPC eine IntegerList?

Beitrag von hubblec4 »

@ Frank Ranis

Für deine Int64List musst du den Code verwenden den Socke gepostet hat.

In deinem Test Beispiel gibst zu Zahlen vor die auch als normaler Integer interpretiert werden können, daher funktioniert alles.

Ich muss größere Zahlen verarbeiten.
In der fuction Item1 - Item2, wird dem Result was völlig anderes zugewiesen. Die Zahlen waren nicht sortiert.

Ich hatte das eben in meinem Programm eingebaut und mir dazu eine neue Unit mit einer Abgeleitete Klasse erstellt wo ich dann direkt

ListInt64.SortASC oder .SortDESC
verwenden kann.

Code: Alles auswählen

 
 
unit uLists;
 
{$mode objfpc}{$H+}
 
interface
 
uses
 Classes, SysUtils, fgl;
 
type
  TInt64List            = specialize TFPGList<Int64>;
 
  TListInt64            = class(TInt64List)
   public
    constructor Create;
    destructor Destroy; override;
 
    procedure SortASC;
    procedure SortDESC;
 
  end;
 
 
implementation
 
 
// Sortieren - von klein nach groß ASC
function SortListASC(const Item1, Item2: Int64): Integer;
begin
  if Item1 = Item2 then Result:= 0
  else
  if Item1 > Item2 then Result:= 1
  else                  Result:=-1;
end;
 
// Sortieren - von groß nach klein DESC
function SortListDESC(const Item1, Item2: Int64): Integer;
begin
  if Item1 = Item2 then Result:= 0
  else
  if Item1 < Item2 then Result:= 1
  else                  Result:=-1;
end;
 
 
 
(*========= public ===========================================================*)
 
// constructor Create
constructor TListInt64.Create;
begin
  inherited Create;                              // TInt64List erzeugen
end;
 
// destructor Destroy
destructor TListInt64.Destroy;
begin
  inherited Destroy;                             // TInt64List zerstören
end;
 
 
// Sortieren - von klein nach groß ASC
procedure TListInt64.SortASC;
begin
  Sort(@SortListASC);
end;
 
// Sortieren - von groß nach klein DESC
procedure TListInt64.SortDESC;
begin
  Sort(@SortListDESC);
end;
 
end.
 
 
 

Antworten