![]() |
AW: statt x-fache „if then else“-Abfragen eine intelligentere Lösung gesucht
@stahli,
danke für deinen Hinweis. :thumb: Das kenne ich, mein Problem ist der sich x-facch wiederholdende *fast* gleiche Code in jeder einzelnen If-Klausel. Eine If Klausel hat ca. 300 Zeilen..... Deswegen mein Ansporn das diese 300 Zeilen nur noch einmal aufgerufen werden und der Dateiname anhand der Userauswahl vorher zusammengestellt wird und dann in dieser einen Procedure genutzt werden kann ohne If-Klauseln für die jeweilige Userauswahl. @Sir Rufo, Erst einmal vielen Dank für die aufklärenden Worte im Post #9!:thumb: Da lag ich ja fast..... ähhh nein ganz daneben mit meiner Annahme auf die Variable bezogen. :oops: Aber wer nicht fragt... Auch für dein Beispeil ohne Generics vielen Dank! Im Moment baue ich noch einiges anderes um. Sobald ich dann ans Aufräumen für das hier besprochene Thema gehe, werde ich mir dein Code ganz genau Schritt für Schritt anschauen. Ich vermute, dass sich mir dabei noch ein paar Fragen stellen werden. Bis hierhin tausend Dank und noch einen schönen Feiertag (zumindest in NRW)! Gruß Jürgen |
AW: statt x-fache „if then else“-Abfragen eine intelligentere Lösung gesucht
@Sir Rufo,
habe jetzt deine Variante mit kleineren Anpassungen erfolgreich umgesetzt. :-D Läuft super und ich habe einiges gelernt! Nochmals Danke!:dp: |
AW: statt x-fache „if then else“-Abfragen eine intelligentere Lösung gesucht
Zitat:
Dazu müsstest du einen einfachen Parser schreiben, der für jede "Variable" (zB. %TITLE%) den passenden Part erstellt und zu einem Builder hinzufügt. Dabei wäre es günstig, einen neuen Part für konstante Teile des Dateinamens zu implementieren (zB. "-miep-" in "%INTERPRET%-miep-%TITLE%"). Der gibt immer den gleichen String zurück. Damit könnte der Anwender den Pfad dann frei konfigurieren :cyclops: Zitat:
Abgesehen davon könnte man auch eine grafische Oberfläche zum einfachen Zusammensetzen eines Builders anbieten. |
AW: statt x-fache „if then else“-Abfragen eine intelligentere Lösung gesucht
Zitat:
Delphi-Quellcode:
Allerdings ist das kein Parser, sondern etwas viel einfacheres: Ein String-Austausch-O-Mat.
Filename := Replace (Filename,'%TITLE%',MyMusic.Title,[rfReplaceAll]);
Filename := Replace (Filename,'%INTERPRET%',MyMusic.Interpret,[rfReplaceAll]); Filename := Replace (Filename,'%DATE%',DateToStr(Date),[rfReplaceAll]); ... Diese Vorgehensweise halte ich persönlich für die flexibelste, weil jederzeit Variablen (bzw. eigentlich ja Platzhalter) hinzugefügt werden können. Eine fortlaufende Numerierung? Nennen wir sie '%NUMBER%'
Delphi-Quellcode:
Das gleiche, nur hier soll die Nummer nur erhöht werden, wenn der Platzhalter existiert.
Filename := Replace (Filename,'%NUMBER%',IntToStr(Number),[rfReplaceAll]);
Inc(Number);
Delphi-Quellcode:
Usw.
if Pos ('%NUMBER%', Filename)>0 then
begin Filename := Replace (Filename,'%NUMBER%',IntToStr(Number),[rfReplaceAll]); inc(Number); end; Du kannst das dann auch auf die Spitze treiben, indem Du einen Skriptinterpreter einbindest. Dann kann der Anwender seine eigenen Namensregeln festlegen. Braucht zwar kaum einer, aber Spaß macht es trotzdem. |
AW: statt x-fache „if then else“-Abfragen eine intelligentere Lösung gesucht
Zitat:
Ich habe das Erstellen eines Builder-Objekts aus dem String vorgeschlagen. |
AW: statt x-fache „if then else“-Abfragen eine intelligentere Lösung gesucht
@BUG,
so wie ich dich verstanden habe schlägst du vor mit reservierten Wörtern zu arbeiten (z.B. "miep"). Das ist jetzt schon ziemlich einfach in dem aufgezeigten FileNameBuilder von Sir Rufo umsetzbar. :-D Dazu würde ich einfach einen neuen TFileNamePart erstellen und entsprechend anwenden. Oder habe ich dich jetzt falsch verstanden? |
AW: statt x-fache „if then else“-Abfragen eine intelligentere Lösung gesucht
Zitat:
Delphi-Quellcode:
Dann könnte man wie folgt für den Builder eine Factory schreiben:
unit FilenameBuilder;
interface uses Classes, Generics.Collections, SysUtils; // ... TFilenamePartFactory = class private FParts : TDictionary<string, IFilenamePart>; public constructor Create; destructor Destroy; override; function GetPart( const AKey : string ) : IFilenamePart; // >> function GetConstantPart( const AString : string ) : IFilenamePart; // << end; // ... implementation // ... TConstantPart = class( TFilenamePart ) public contructor create(AString: String); protected function Build( const AData : TMP3Meta ) : string; override; private constantString: string; end; // ... function TFilenameBuilder.GetFilename( const AData : TMP3Meta ) : string; var LBuilder : TStringBuilder; LIdx : Integer; begin LBuilder := TStringBuilder.Create; try for LIdx := 0 to FParts.Count - 1 do begin // "-" entfernt LBuilder.Append( FParts[LIdx].Build( AData ) ); end; Result := LBuilder.ToString; finally LBuilder.Free; end; end; // ... { TConstantPart } constructor TConstantPart.create(AString: string) begin constantString := AString; end; function TConstantPart.Build( const AData : TMP3Meta ) : string; begin Result := constantString; end; { TFilenamePartFactory } // ... function TFilenamePartFactory.GetConstantPart( const AString : string ) : IFilenamePart; begin Result := TConstantPart.create(AString); end; end.
Delphi-Quellcode:
Dar Parser lässt noch viel Raum für Verbesserung, sollte aber als zur Verdeutlichung taugen.
type TFilenameBuilderFactory = class
public constructor create(AFactory: TFilenamePartFactory; ownsFactory: boolean = true); destructor destroy; override; (** Returns a *new* object, caller handles destruction. *) function createBuilder(AString : string): TFilenameBuilder; private FFactory: TFilenamePartFactory; FOwnsFactory: boolean; // non-constant state FInVariable: boolean; FBuffer: string; // invariant: length(FBuffer) = 0 FBuilder: TFilenameBuilder; // invariant: FBuilder = nil // methods procedure flushBuffer; end; constructor TFilenameBuilderFactory.create(AFactory: TFilenamePartFactory; ownsFactory: boolean); begin FFactory = AFactory; FOwnsFactory = ownsFactory; setLength(buffer, 0); FBuilder = nil; end; destructor TFilenameBuilderFactory.destroy begin if FOwnsFactory then FFactory.free(); end; procedure TFilenameBuilderFactory.flushBuffer; var tempPart: IFilenamePart; begin if (length(FBuffer) > 0) then begin if inVariable then tempPart := AFactory.GetPart(FBuffer) // not sure what TDirectory.getItem does when key does not exist!!! else tempPart := AFactory.GetConstantPart(FBuffer); ABuilder.add(tempPart); end; setLength(FBuffer, 0); end; function TFilenameBuilderFactory.createBuilder(AString : string): TFilenameBuilder; var position: integer; begin FBuilder = TFilenameBuilder.create(); inVariable = false; for position := 1 to length(string) do begin if (AString[position] = '%') then begin flushBuffer(); inVariable = not inVariable; end else begin FBuffer := FBuffer + AString[position]; end; end; flushBuffer(); result = FBuilder; FBuilder = nil; end; Achtung: Ich habe lange kein Delphi mehr benutzt, sind also wahrscheinlich Fehler drin. Anmerkung zur Code-Qualität sind natürlich erwünscht :mrgreen: |
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:34 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz