SringList sortiert merkwürdig

Rund um die LCL und andere Komponenten
Antworten
Andrewi
Beiträge: 18
Registriert: Fr 8. Mär 2013, 16:07
OS, Lazarus, FPC: MINT 21, Laz: 2.2.0, FPC: 3.2.2
CPU-Target: x64
Wohnort: Hzgt. Lauenburg

SringList sortiert merkwürdig

Beitrag von Andrewi »

Hallo zusammen!

Ich habe ein Verständnisproblem bei der Sortierung in einer Stringliste. Ich lese Daten aus einer SQLite-Tabelle (UTF8) in eine Stringliste ein. Sorted ist TRUE. Dabei bekomme ich eine merkwürdige Sortierung:

1
5
Ärger
Aal
Aaron
Ökonom
Öl

Berta
Cäsar
...
...
Zeppelin.

Wenn ich die selben Daten in eine sortierte List~ / Combobox einlese, ist die Sortierung korrekt. Hat jemand eine Ahnung woran das liegt / liegen könnte? Hintergrund ist, daß die Daten sortiert in einer PickList anzeigen möchte und ich dort keine Möglichkeit zur Sortierung gefunden habe.

Zum Einsatz kommen Lazarus 1.4.0 und FPC 2.6.4 auf Win7 und Win10.

Grüße und vielen Dank im Vorraus
André

Mathias
Beiträge: 6904
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: SringList sortiert merkwürdig

Beitrag von Mathias »

Wen ich folgendes mache, kommt es bei mir anders als bei dir:

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
var
  sl: TStringList;
begin
  sl := TStringList.Create;
  sl.Sorted:=True;
  sl.Add('a');
  sl.Add('b');
  sl.Add('c');
  sl.Add('ä');
  sl.Add('ö');
  sl.Add('ü');
  sl.Add('u');
  sl.Add('a');
  sl.Add('1');
  sl.Add('5');
  sl.Add('Ärrger');
  sl.Add('Aal');
  sl.Add('Aaron');
  sl.Add('Ökonom');
  sl.Add('Öl');
  sl.Add('Berta');
  sl.Add('Cäsar');
  sl.Add('...');
  sl.Add('...');
  sl.Add('Zeppelin.');
  sl.Add('sl.Sort;');
//  sl.Sort;
  Memo1.Text := sl.Text;
  sl.Free;
end;   

Code: Alles auswählen

...
1
5
a
ä
Aal
Aaron
Ärger
b
Berta
c
Cäsar
ö
Ökonom
Öl
sl.Sort;
u
ü
Zeppelin.
Doppelte Werte werden gelöscht.

Ich verwende FPC 3.1.1, vielleicht ligt es an dem.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: SringList sortiert merkwürdig

Beitrag von Winni »

Hallo!

sl : TStringList;
(...)

sl := TStringList.create;
sl. Sorted := false; // !!!

(* Daten einlesen ... *)

sl.Sorted := true; // Bei großen Datenmengen und schlappem Rechner: warten ...

Das war schon in Delphi (1, 2, 3 ....) schlecht dokumentiert.

Grüße
Winni

Socke
Lazarusforum e. V.
Beiträge: 3177
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: SringList sortiert merkwürdig

Beitrag von Socke »

Winni hat geschrieben:sl := TStringList.create;
sl.Sorted := false; // !!!
[...]
Das war schon in Delphi (1, 2, 3 ....) schlecht dokumentiert.
Warum sollte man denn die Sortierung ausschalten? TStringList führt beim Anfügen (Add) eine binäre Suche aus um die Zielposition zu finden; daher bleibt die Sortierung erhalten. Fachlich wäre das also vollkommen in Ordnung.
Dass ein Quicksort am Ende schneller sein kann als mehrfache binäre Suchen liegt einigermaßen klar auf der Hand.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: SringList sortiert merkwürdig

Beitrag von Winni »

Hallo!

Ganz einfach: weil die frühen Delphi- und auch die frühen Lazarus-Versionen sich einen Dreck darum gekümmert haben, wie Boolean Sorted beim TSringlist.add stand - sie haben immer hinten angefügt. .Erst das Umstellen von Sorted von false auf true erbrachte die Sortierung.

Vom derzeitigen Stand hab ich keine Ahnung. Jedenfalls funktioniert meine Lösung - und darum ging's ja wohl.

Grüße
Winni

Socke
Lazarusforum e. V.
Beiträge: 3177
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: SringList sortiert merkwürdig

Beitrag von Socke »

Winni hat geschrieben:Ganz einfach: weil die frühen Delphi- und auch die frühen Lazarus-Versionen sich einen Dreck darum gekümmert haben, wie Boolean Sorted beim TSringlist.add stand - sie haben immer hinten angefügt. .Erst das Umstellen von Sorted von false auf true erbrachte die Sortierung.
Bei TStrings ist dies auch immer noch der Stand; TStrings selbst kann gar nicht soriteren und kann das daher nicht beachten. TStringList hingegen schon.
Daher kann es Unterschiede geben, wenn man die Strings zuerst in ein TStringList einliest oder direkt bei der Komponente anhängt.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Andrewi
Beiträge: 18
Registriert: Fr 8. Mär 2013, 16:07
OS, Lazarus, FPC: MINT 21, Laz: 2.2.0, FPC: 3.2.2
CPU-Target: x64
Wohnort: Hzgt. Lauenburg

Re: SringList sortiert merkwürdig

Beitrag von Andrewi »

Hallo zusammen!

Erstmal viele Dank für eure Antworten. Ich habe den Tip von Winni, Sorted:= FALSE-Daten einlesen-Sorted := TRUE ausprobiert. Es hat sich nicht am Ergebnis geändert. Ich habe mal das Ergebnis als Bild angefügt. Einmal eine ListBox mit Sorted := TRUE, 1 ListBox mit Sortetd := FALSE und ein Memo. Alle drei Komponenten werden aus der selben Stringliste (Sorted := TRUE) gefüttert. Ich habe mal ein Bild mit dem Ergebnis angefügt. Was mich am meisten wundert, ist, daß der über ListBox.Items / Memo.Lines ausgelesene Eintrag bei allen 3 Kompos gleich ist, obwohl die Anzeige sich unterscheidet. :?:
https://www.magentacloud.de/lnk/f4jkLfgn

Grüße

André
Ein Mensch meint gläubig wie ein Kind, dass alle Menschen Menschen sind. (Eugen Roth)

Mathias
Beiträge: 6904
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: SringList sortiert merkwürdig

Beitrag von Mathias »

Was passiert, wen du folgendes aufrufst ?

Code: Alles auswählen

sl.Sort;
Dafür aber

Code: Alles auswählen

sl.Sorted:=True; 
weglässt.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Andrewi
Beiträge: 18
Registriert: Fr 8. Mär 2013, 16:07
OS, Lazarus, FPC: MINT 21, Laz: 2.2.0, FPC: 3.2.2
CPU-Target: x64
Wohnort: Hzgt. Lauenburg

Re: SringList sortiert merkwürdig

Beitrag von Andrewi »

Hallo Mathias!
Auch bei deiner Idee, mit sl.Sort anstatt sl.Sorted := TRUE, bleibt das Ergebnis gleich. Es hat leider keine Auswirkung. Ich frage mich, wo der Unterschied in der Anzeige-Sortierung der Listbox1 und der Sortierung der eigentlichen Liste liegt. Denn die Abfrage der Items führt ja zu einem Ergebnis, das eindeutig von der Anzeige abweicht:

Code: Alles auswählen

procedure TForm4.FormCreate(Sender: TObject);
begin
  slZutat.Sort;
  ListBox1.Items := slZutat;
  ListBox2.Items := slZutat;
  Memo1.Text := slZutat.Text;
  Label4.Caption := Label4.Caption + ListBox1.Items.Strings[4];
  Label5.Caption := Label5.Caption + ListBox2.Items.Strings[4];
  Label6.Caption := Label6.Caption + Memo1.Lines[4];
end;
 
Danach bringen ja alle 3 Abfragen das selbe Ergebnis, obwohl der ermittelte Eintrag in der Listbox1 eigentlich erst an 13. Stelle kommt. Bin ich hier über einen Bug gesolpert oder nur zu blöd die Sortiereinstellungen richtig anzuwenden :?:

Grüße André
Ein Mensch meint gläubig wie ein Kind, dass alle Menschen Menschen sind. (Eugen Roth)

Mathias
Beiträge: 6904
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: SringList sortiert merkwürdig

Beitrag von Mathias »

Danach bringen ja alle 3 Abfragen das selbe Ergebnis,
Wieso sollten die verschiedene Ergebnisse haben ?

Du lädst hier alle 3 Elemente mit dem gleichen slZutat.

Code: Alles auswählen

  ListBox1.Items := slZutat;
  ListBox2.Items := slZutat;
  Memo1.Text := slZutat.Text;
Mit

Code: Alles auswählen

sl.Sorted := TRUE,
wird fortlaufend bei jeder Änderung der Liste immer neu sortiert, braucht dem entsprechend viel Ressourcen.
Mit

Code: Alles auswählen

sl.Sort 
wird nur bei Aufruf dieses Befehles sortiert.

Oder verstehe ich deine Frage falsch ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Andrewi
Beiträge: 18
Registriert: Fr 8. Mär 2013, 16:07
OS, Lazarus, FPC: MINT 21, Laz: 2.2.0, FPC: 3.2.2
CPU-Target: x64
Wohnort: Hzgt. Lauenburg

Re: SringList sortiert merkwürdig

Beitrag von Andrewi »

Hallo Mathias!

Ich hatte beim vorletzten Post einen Screenshot angehängt. Danach ist die Anzeige der Listbox1 (Sorted := TRUE) eine andere, als bei der Listbox2 (Sorted := FALSE). Der Eintrag "Äpfel, säuerlich" wird in der Listbox1 an 13. Stelle angezeigt, bei der Listbox2 an 4. die Abbfrage mit Listbox.Items.Strings[4] ergibt aber bei beiden Boxen das selbe Ergebnis.
Aber das eigentliche Problem habe ich leider immer noch nicht lösen können. Es ist egal, ob ich sl.Sort od. sl.Sorted := TRUE verwende, bekomme ich keine ordentlich Sortierung hin. Könnte das mit der Codierung UTF8 zusammenhängen, sprich müßte ich zunächst UTF8ToSys --> sortieren --> SysToUTF8 einsetzen???

Grüße André
Ein Mensch meint gläubig wie ein Kind, dass alle Menschen Menschen sind. (Eugen Roth)

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: SringList sortiert merkwürdig

Beitrag von Michl »

Andrewi hat geschrieben:Wenn ich die selben Daten in eine sortierte List~ / Combobox einlese, ist die Sortierung korrekt. Hat jemand eine Ahnung woran das liegt / liegen könnte?
Die Frage ist zwar schon etwas älter, da sie noch niemand beantwortet hat und ich aufgrund eines Bugfixes eben in die Source geschaut habe, kann ich eine Antwort auf die Frage geben. Es liegt einfach daran, dass unter Windows eine native StringList (TWin32ListStringList) für die Controls eingesetzt wird.

Schön ist bei diesem Beispiel der fortlaufende Entwicklungsprozess von Lazarus zu erkennen (Windows):

Einträge:

Code: Alles auswählen

Berta
Ärger
Aaron
Öl
1
In Lazarus 1.4.4 sortiert die StringList "falsch":

Code: Alles auswählen

1
Ärger
Aaron
Öl
Berta
In Lazarus 1.6.0 sortiert die StringList anders, aber immer noch nicht "richtig" (zumindest, wie Windows dies macht):

Code: Alles auswählen

1
Aaron
Berta
Ärger
Öl

Das Gute ist, die Sortierung einer StringList stimmt im Lazarus Trunk mit der von Windows überein:

Code: Alles auswählen

1
Aaron
Ärger
Berta
Öl

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

Mathias
Beiträge: 6904
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: SringList sortiert merkwürdig

Beitrag von Mathias »

@Michel

Hast du es mit Linux auch probiert, oder bist du ein reiner Windows-Programmierer ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: SringList sortiert merkwürdig

Beitrag von Michl »

Bis auf einen kurzen Androidausflug habe ich bisher Lazarus nur für Windows genutzt.

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

Antworten