Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi TStringList.Sort (https://www.delphipraxis.net/213816-tstringlist-sort.html)

H.Bothur 30. Sep 2023 17:00

TStringList.Sort
 
Moin,

ich stehe gerade ein bisschen auf dem Schlauch, ich habe eine TStringList mit folgendem Inhalt (gekürzt):

Delphi-Quellcode:
0002 F: ADDAMS_FAMILY Titel D1-03.avi
0003 F: ADDAMS_FAMILY Titel D1-04.avi
0004 F: ADDAMS_FAMILY Titel D1-05.avi
0005 F: ADDAMS_FAMILY Titel D1-06.avi
0006 F: ADDAMS_FAMILY Titel D1-07.avi
0007 F: ADDAMS_FAMILY Titel D1-08.avi
0008 F: ADDAMS_FAMILY Titel D1-09.avi
0009 F: ADDAMS_FAMILY Titel D1-10.avi
0011 F: Akte Ex-1-1_ Endlich Prinzessin (S01_E01).mp4
0012 F: Akte Ex-1-2_ Mord am Weinberg (S01_E02).mp4
0013 F: Akte Ex-1-3_ Der fröhliche Mönch (S01_E03).mp4
0014 F: Akte Ex-1-4_ Im Rausch der Ermittlungen (S01_E04).mp4
0015 F: Akte Ex-1-5_ Schweinkram (S01_E05).mp4
0016 F: Akte Ex-1-6_ Fernweh (S01_E06).mp4
0017 F: Akte Ex-1-7_ Ommm (S01_E07).mp4
0018 F: Akte Ex-1-8_ Die Prophezeiung (S01_E08).mp4
0019 F: Akte Ex-2-1_ Treu bis ins Grab (S02_E01).mp4
0020 F: Akte Ex-2-2_ Ohne Spritze (S02_E02).mp4
0001 S: Addams Family
0010 S: Akte Ex
Wenn ich jetzt die Liste über
Delphi-Quellcode:
StringList.sort
sortiere hätte ich erwartet das die beiden letzten Zeilen entsprechend einsortiert werden - werden die aber komischerweise nicht sondern leiben unten stehen.

Warum bzw. wo denke ich falsch ?

Hans

himitsu 30. Sep 2023 17:26

AW: TStringList.Sort
 
Da wir nicht sehen wie du es machst ... keine Ahnung.

Grundsätzlich funktioniert es.
Abgesehn, der Text wäre nicht wirklich genau der, welchen du hier zeigst. (nicht sichtbare Zeichen, die Ziffern nicht wirklich DIESE Ziffern, sondern andere Unicodezeichen usw.)

H.Bothur 30. Sep 2023 17:42

AW: TStringList.Sort
 
Hier der komplette Source:

Delphi-Quellcode:
unit SerienDatabase;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls, Vcl.ExtCtrls;

type
  TSerienDB = class(TForm)
    BtnPlay: TButton;
    BtnLaden: TButton;
    LbEVerzeichnis: TLabeledEdit;
    Memo1: TMemo;
    procedure BtnLadenClick(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  SerienDB: TSerienDB;
  LfdNummer: Integer;

implementation

{$R *.dfm}

procedure FindAllFiles(RootFolder: string; Mask: string = '*.*'; Recurse: Boolean = True);
var
  SR: TSearchRec;
  DateiListe: TStringList;
begin
  RootFolder := IncludeTrailingPathDelimiter(RootFolder);
  DateiListe := TStringList.Create;
  DateiListe.Sorted := true;

  if Recurse then
    if FindFirst(RootFolder + '*.*', faAnyFile, SR) = 0 then
      try
        repeat
          if SR.Attr and faDirectory = faDirectory then
            // --> ein Verzeichnis wurde gefunden
            if (SR.Name <> '.') and (SR.Name <> '..') then
            begin
              (* Verzeichnis gefunden *)
              DateiListe.Add(Format('%.*d', [4, LfdNummer]) +' S: ' +SR.Name);
              LfdNummer := LfdNummer +1;
              FindAllFiles(RootFolder + SR.Name, Mask, Recurse);
            end;
        until FindNext(SR) <> 0;
      finally
        FindClose(SR);
      end;
  if FindFirst(RootFolder + Mask, faAnyFile, SR) = 0 then
    try
      repeat
        if SR.Attr and faDirectory <> faDirectory then
        begin
          // --> eine Datei wurde gefunden
          DateiListe.Add(Format('%.*d', [4, LfdNummer]) +' F: ' +SR.Name);
          LfdNummer := LfdNummer +1;
        end;
      until FindNext(SR) <> 0;
    finally
      FindClose(SR);
    end;
    Dateiliste.Sort;
    SerienDB.Memo1.Lines.AddStrings(DateiListe);
    DateiListe.Free;
end;

procedure TSerienDB.BtnLadenClick(Sender: TObject);
begin
  LfdNummer := 1;
  FindAllFiles(LbEVerzeichnis.Text);
end;

end.
Der Sort kommt bevor ich die StringList an das Memo zur Anzeige übergebe - es wird nur nicht sortiert. :-( Oder - blöde gefrafg, muss ich generell die Sortierfunktion selber dazuschreiben ? Ich hätte gedacht das es so eine normale Ascii-Sortierung geben sollte.

Hans

Uwe Raabe 30. Sep 2023 19:54

AW: TStringList.Sort
 
Lass mal das
Delphi-Quellcode:
DateiListe.Sorted := true;
weg oder füge ein
Delphi-Quellcode:
DateiListe.Duplicates := dupIgnore
davor ein.

himitsu 30. Sep 2023 20:28

AW: TStringList.Sort
 
Da jeweils nur ein Verzeichnis in sich sortiert wird...

Kann es sein, dass die beiden Letzten in einem anderen Verzeichnis liegen?
Sag ja. :zwinker:

Weißt du was ein Debugger ist?
Haltepunkt auf
Delphi-Quellcode:
SerienDB.Memo1.Lines.AddStrings
und "nicht" wundern, warum das zwei Mal aufgerufen wird.


UND
Warum ist LfdNummer eine globale Variable?
Warum ist FindAllFiles keine Methode von von TSerienDB? (die würde schön ins private passen)
Warum ...

PS: Delphi-Referenz durchsuchenTDirectory.GetFiles

H.Bothur 30. Sep 2023 21:35

AW: TStringList.Sort
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1527560)
Lass mal das
Delphi-Quellcode:
DateiListe.Sorted := true;
weg oder füge ein
Delphi-Quellcode:
DateiListe.Duplicates := dupIgnore
davor ein.

Ich hab das
Delphi-Quellcode:
DateiListe.Sorted := true;
rausgenommen - ändert leider nichts :(

Hans

H.Bothur 30. Sep 2023 21:43

AW: TStringList.Sort
 
Zitat:

Zitat von himitsu (Beitrag 1527561)
Da jeweils nur ein Verzeichnis in sich sortiert wird...

Kann es sein, dass die beiden Letzten in einem anderen Verzeichnis liegen?
Sag ja. :zwinker:

Nein :-) die beiden letzten sind die Verzeichnisse in denen die anderen Dateien liegen.

Zitat:

Weißt du was ein Debugger ist?
Haltepunkt auf
Delphi-Quellcode:
SerienDB.Memo1.Lines.AddStrings
und "nicht" wundern, warum das zwei Mal aufgerufen wird.
Ja - aber alle Zeilen sind trotzdem nur einmal in dem Memo - ich habe aber mal die Dateiliste als gloibale Variable genommen (ja - pfui) und die BtnClick verändert:

Delphi-Quellcode:
procedure TSerienDB.BtnLadenClick(Sender: TObject);
begin
  LfdNummer := 1;
  DateiListe := TStringList.Create;
  FindAllFiles(LbEVerzeichnis.Text);
  Dateiliste.Sort;
  SerienDB.Memo1.Lines.AddStrings(DateiListe);
  DateiListe.Free;
end;
Dann kommt das spannenderweise passend raus :-)

Zitat:

UND
Warum ist LfdNummer eine globale Variable?
Weil ich nicht wusste wie ich das am besten mache wenn ich die procedure rekursiv aufrufe

Zitat:

Warum ist FindAllFiles keine Methode von von TSerienDB? (die würde schön ins private passen)
Warum ...
Weil ich immer noch nicht das Konzept mit den Methoden und so verstanden habe - sorry, da hänge ich halt immer noch in den 80ern bei TP3.0

Zitat:

PS: Delphi-Referenz durchsuchenTDirectory.GetFiles
Oh, das kannte ich nicht, das kucke ich mir morgen mal an !

Gruss
Hans

Uwe Raabe 30. Sep 2023 21:58

AW: TStringList.Sort
 
Beim rekursiven Aufruf von FindAllFiles wird aber jedes mal eine eigene DateiListe gefüllt und am Ende in das Memo übertragen. Das Sort wirkt dann halt auch nur auf die gerade aktuelle Instanz. Du solltest die DateiListe als Parameter an FindAllFiles übergeben und das Sort wie auch das Übertragen ins Memo außerhalb (also z.B. in BtnLadenClick) machen.

mytbo 30. Sep 2023 23:05

AW: TStringList.Sort
 
Zitat:

Zitat von H.Bothur (Beitrag 1527556)
Hier der komplette Source: ...
Der Sort kommt bevor ich die StringList an das Memo zur Anzeige übergebe - es wird nur nicht sortiert.

Trenne Dateisuche/Datensammlung und Formatierung. Wenn ich deinen Quelltext richtig verstanden habe, möchtest du Folgendes (ohne Sortierung):
Delphi-Quellcode:
function FindPlayFiles(pmFileList: TStringList; const pmcPath: String; const pmcSearchMask: String = '*'; pmWithSubDirs: Boolean = True): Boolean;
const
  SEARCH_OPTION: array[Boolean] of TSearchOption = (TSearchOption.soTopDirectoryOnly, TSearchOption.soAllDirectories);
begin
  Result := False;
  if pmFileList = Nil then Exit; //=>
  if not TDirectory.Exists(pmcPath) then Exit; //=>

  var files: TStringDynArray := TDirectory.GetFiles(pmcPath, pmcSearchMask, SEARCH_OPTION[pmWithSubDirs]);
  if Length(files) > 0 then
  begin
    pmFileList.Clear;
    pmFileList.AddStrings(files);
    Result := True;
  end;
end;

procedure FormatPlayList(pmFmtList: TStrings; const pmcRootDir: String; pmFileList: TStringList; pmStartNumber: Integer = 1);
begin
  if pmFmtList = Nil then Exit; //=>
  if pmFileList = Nil then Exit; //=>
  if pmFileList.Count = 0 then Exit; //=>
 
  pmFmtList.BeginUpdate;
  try
    var run, currentDir: String;
    for var i: Integer := 0 to pmFileList.Count - 1 do
    begin
      run := TPath.GetDirectoryName(pmFileList[i]);
      if currentDir <> run then
      begin
        currentDir := run;
        pmFmtList.AddObject(Format('%.4d S: %s', [pmStartNumber, currentDir.Substring(Length(pmcRootDir))]), TObject(-1));
        Inc(pmStartNumber);
      end;

      pmFmtList.AddObject(Format('%.4d F: %s', [pmStartNumber, TPath.GetFileName(pmFileList[i])]), TObject(i));
      Inc(pmStartNumber);
    end;
  finally
    pmFmtList.EndUpdate;
  end;
end;

begin
  SerienDB.Memo.Lines.Clear;
  if FindPlayFiles(FFileList, FRootDir) then
    FormatPlayList(SerienDB.Memo.Lines, FRootDir, FFileList);
Disclaimer: Der Entwurf ist nur eine Überarbeitung des Originals.

Bis bald...
Thomas

himitsu 30. Sep 2023 23:45

AW: TStringList.Sort
 
Da die Daten bereits sortiert erstellt werden, ist ein nochmaliges Sortieren nutzlos,
und da es bereits eine übergreifende/lobale Komponente gibt, kann man sie auch direkt verwenden,
...
also einfach direkt ins Memo einfügen.

Ja, ein Memo ist langsam, aber
* wieviele Zeilen werden es denn? (keine 10-tausende und mehr, oder?)
* und Delphi-Referenz durchsuchenTStrings.BeginUpdate



Ja, als Parameter die Liste durchreichen

oder die Listen als Result rausgeben (für ein einfacheres Speichermanagement als String-Array, anstatt als Listen-Komponente)
und schon kann man das Ergebnis in die Liste des Aufrufers einfügen/übernehmen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:56 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz