![]() |
Sortierfunktion nach Datum in einer TStringList
Hallo zusammen,
ich hatte bisher beim Einlesen von Dateien in eine StringList das Datum der jeweiligen Datei als Integerwert in das jeweilige Object der StringList gespeichert und konnte die StringList somit gut nach Datum sortieren. Wenn Dateien das gleiche Datum hatten, wurde dann nach Dateiname sortiert
Delphi-Quellcode:
function DoCompareByDate(List: TStringList; Index1, Index2: Integer): Integer;
begin Result := 0; if Assigned(List) then begin if (Integer(List.Objects[Index1]) < Integer(List.Objects[Index2])) then begin Result := 1; end else if (Integer(List.Objects[Index1]) > Integer(List.Objects[Index2])) then begin Result := -1; end; end; end; Nun kann ich das Datum nicht mehr als Object in der StringList speichern, da was anderes dafür vorgesehen ist. Meine derzeitiges Konzept: Damit ich weiterhin auch nach Datum sortieren kann, würde ich beim Einlesen der Dateien eine *zweite, neue* Stringlist füllen, welche dieselbe Object-ID erhält wie die "Master"-StringList. In der zweiten Stringlist würde ich dann nur das Datum speichern. Meine Datumssortierfunktion könnte dann auf diese 2. Liste angewendet werden. Meine Fragen: - Wie bekomme ich die "Master" Stringlist so sortiert wie die Datums-StringList (beide Object-Ids sind ja gleich)? - Gibt es evtl. alternative Konzept-Vorschläge? Edit: Eine Umstellung der vorhandenen Master-TStringList auf z.B. TObjectList würde ich nur sehr, sehr ungern vornehmen... Vielen Dank schon mal im Voraus! |
AW: Sortierfunktion nach Datum in einer TStringList
Wieso erstellst Du nicht eine Klasse, die alle benötigten Daten enthält, und hinterlegst diese dann in der Objects-Eigenschaft? Dafür ist diese ja auch eigentlich vorgesehen, Du musst nur daran denken, diese beim Löschen eines Eintrags auch wieder freizugeben bzw. freigeben zu lassen.
|
AW: Sortierfunktion nach Datum in einer TStringList
Alternativ kann man auch eine neue von TStringList abgeleitete Klasse erstellen, die die nötigen Attribute enthält, und diese statt der TStringList nutzen.
MfG Dalai |
AW: Sortierung einer "Master"-TStringList nach der Reihenfolge einer 2. TStringList
Hallo,
danke für die Antworten. In einem neuen Projekt würde ich in diesem Fall mit Objekten arbeiten, auch wenn ich mich momentan damit noch nicht so auskenne. Da aber schon viele Anpassungen meiner jetzigen TStringList-Methoden erfolgt sind (z.B. sichern der Zahl (Datum) aus dem Object über die SaveToFile- oder SaveToStream-Methoden, LoadFromFile, usw.), möchte ich für dieses Projekt keine so großen Änderungen mehr vornehmen. Was mir jetzt nur noch fehlt ist die Sortierung meiner "Master"-TStringList nach der zweiten Datums-TStringList. In beiden Listen sind in den Objecten die gleichen eindeutigen Zahlen gespeichert. Das heißt, beim befüllen der beiden TStringListen werden die jeweiligen Objecte mit den gleichen eindeutigen Nummern versehen. Z. B. enthalten beide Listen im 4. Item die Object-Nr 8815468541, im 5. Item die Object-Nr 8815468542 usw. Nun sortiere ich die zweite TStringList nach Datum, welches in den Items hinterrlegt ist. Wie bekomme ich nun die Master-StringList so sortiert, dass diese dieselbe Reihenfolge hat wie die zweite TSringList? (Reihenfolge = die in dem Object hinterlegte Nummer) Ich hoffe ich konnte mich verständlich ausdrücken was die Sortieranforderung betrifft. Edit: Titel geändert. |
AW: Sortierfunktion nach Datum in einer TStringList
Egal wie du es machst, es wird extrem ineffizient werden, weil du in einer Stringlist nach einem bestimmten Wert in Objects nur sequentiell suchen kannst.
Wenn du nur zum Sortieren in eine extra Stringlist in Items das Datum schreibst und in Objects alle zu diesem Datum gehörenden Daten, dann kannst du, wenn im restlichen Programm eine Änderung der Datenstruktur zu kompliziert ist, nach dem Sortieren die Daten wieder in deine zwei Stringlisten aufteilen, bzw. ausgehend von deiner nach Datum sortierten Stringlist die zweite Stringliste neu erstellen. |
AW: Sortierfunktion nach Datum in einer TStringList
Ich (und vermutlich auch ein paar andere User) habe ein Problem damit, zusammengehörige Daten in unterschiedlichen Listen zu hinterlegen, das ist extrem fehleranfällig, vor allem dann, wenn aus welchen Gründen auch immer die Listen unterschiedlich viele Einträge enthalten, da sind AVs einfach vorprogrammiert. Von daher würde ich eher zur TObjectList tendieren, die kannst Du nach eigenem Gusto (um)sortieren, und eine Methode zur Ausgabe ist ja auch schnell geschrieben. Das mag zwar im Moment etwas Aufwand sein, aber erstens ist der überschaubar und zweitens zahlt sich das langfristig aus.
|
AW: Sortierfunktion nach Datum in einer TStringList
Danke an alle beteiligten! :dp:
Wie ich jetzt gemerkt habe, kann ich machen was ich will, ich habe immer irgendein Problem, solange ich nicht die Struktur ändere. Ich schreibe nun wie ursprünglich erst einmal das Datum als Integer wieder in das jeweilige Object des Item. Die andere Erweiterung muss warten. Dieser Thread ist somit gelöst! |
AW: Sortierfunktion nach Datum in einer TStringList
Das ist eigentlich alles was du brauchst:
Delphi-Quellcode:
Da sammelst du alle Instanzen, sortierst diese, wie gewünscht und lässt dir mit den beiden Methoden die StringListen befüllen:
unit MyObjectList;
interface uses {System.}Classes, {System.}Generics.Collections, {System.}SysUtils; type TMyObjectList<T: class> = class( TObjectList<T> ) public procedure ToStrings( AStrings: TStrings; IncludeObjects: Boolean = false ); overload; procedure ToStrings( AStrings: TStrings; AConverter: TFunc<T, string>; IncludeObjects: Boolean = false ); overload; end; implementation { TMyObjectList<T> } procedure TMyObjectList<T>.ToStrings( AStrings: TStrings; IncludeObjects: Boolean ); begin ToStrings( AStrings, function( AItem: T ): string begin Result := AItem.ToString( ); end, IncludeObjects ); end; procedure TMyObjectList<T>.ToStrings( AStrings: TStrings; AConverter: TFunc<T, string>; IncludeObjects: Boolean ); var LItem: T; begin AStrings.BeginUpdate; try AStrings.Clear; for LItem in Self do begin if IncludeObjects then AStrings.AddObject( AConverter( LItem ), LItem ) else AStrings.Add( AConverter( LItem ) ); end; finally AStrings.EndUpdate; end; end; end.
Delphi-Quellcode:
FFileInfos : TMyObjectList<TFileInfo>;
FFileInfos.Sort( {Sortier-Methode} ); // Sortierung für ListBox FFileInfos.ToStrings( ListBox1.Items, True ); FFileInfos.Sort( {Sortier-Methode} ); // Sortierung für ComboBox FFileInfos.ToStrings( ComboBox1.Items, function ( Item: TFileInfo ) : string begin Result := Format('%s (%d)',[Item.Name,Item.Size]); end, True ); |
AW: Sortierfunktion nach Datum in einer TStringList
Wie DeddyH würde ich auch raten, keine 2 Stringlisten zu benutzen. Die irgendwie zu synchronisieren ist echt zu fehlerträchtig, weil dann zwie Datenquellen vorhanden sind. Vor allem ist das aber auch unnötig. Deddy hat sa vielleicht zu knapp beschrieben.
Ich denke er meint (ungefähr zumindest) das, was ich jetzt etwas ausführlicher schreibe. Der Vorteil einer TObjectList ist ja der, dass man in die einzelnen Objekte dieser Liste so ziemlich alle Datentypen die es gibt, reinpacken kann. Definiere dir also einen Typ, der zumindest alles enthält, was angezeigt werden soll. Da geht natürlich auch noch mehr. Diese TObjectList füllst du dann mit deinen Daten. Jetzt kommt das Stringgrid. Dieses wird gefüllt aus der TObjectList. Soll dieses jetzt sortiert werden, dann sortierst du die TObjectList, machst das Stringgrid leer und befüllst es wieder aus der sortierten TObjectList. Das wars dann. Wegen der TObjectList : das ist zwar Allzweckwaffe, aber man muss diese auch richtig benutzen. Beim Delphi-Treff gibts ein gutes Tutorial dazu. |
AW: Sortierfunktion nach Datum in einer TStringList
@juergen
Also die Idee von DeddyH ist wohl die Beste. Wenn Objekt bereits belegt ist, dann eine Klasse schreiben die sowohl dieses Objekt enthält wie auch ein Zweites. Letztendlich die einfachste Methode. Trotzdem, hier mal eine "Trick 17" Methode. Liste (TStringList) enthält 1000 Daten mit Uhrzeiten. Dennoch wird sie korrekt alphabetisch sortiert. Der eigentliche Trick ist, dass die Daten anders gespeichert sind als sie angezeigt werden:
Delphi-Quellcode:
function DateTimeFormatDE: TFormatSettings;
begin Result.DateSeparator := '.'; Result.TimeSeparator := ':'; Result.ShortDateFormat := 'dd/MM/yyyy hh:nn:ss'; end; function DateTimeFormatINT: TFormatSettings; begin Result.DateSeparator := '-'; Result.TimeSeparator := ':'; Result.ShortDateFormat := 'yyyy/MM/dd hh:nn:ss'; end; procedure ListeMitZufaelligenDatenGenerieren(List: TStrings; Max: Integer); var i: Integer; dt: TDateTime; begin for i := 1 to Max do begin dt := EncodeDateTime(Random(115) + 1900, Random(12) + 1, Random(28) + 1, Random(24), Random(60), Random(60), Random(1000)); List.Add(DateTimeToStr(dt, DateTimeFormatDE)); //erstelle deutsch-typsch end; end; procedure DatenInListeInAnderesFormatAendern(List: TStrings); var i: Integer; dt: TDateTime; begin for i := 0 to List.Count - 1 do begin dt := StrToDateTime(List[i], DateTimeFormatDE); //lese deutsch-typsch List[i] := DateTimeToStr(dt, DateTimeFormatINT); //verändere international end; end; procedure TForm1.FormCreate(Sender: TObject); begin //Datum deutsch-typisch 27.03.2015 14:58:36. Für Sortierung ungeeigent ListeMitZufaelligenDatenGenerieren(ListBox1.Items, 1000); //Datum untypisch 2015-03-27 14:58:36. Für Sortierung geeignet DatenInListeInAnderesFormatAendern(ListBox1.Items); ListBox1.Sorted := True; ListBox1.Style := lbOwnerDrawFixed; end; procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState); var Delta: Integer; dt: TDateTime; s: String; begin with (Control as TListbox) do begin //Das Datum ist in der StringList untypisch gespeichert: 2015-03-27 14:58:36 //Hier wird es für die typische Darstellung 27.03.2015 14:58:36 verändert. dt := StrToDateTime(Items[Index], DateTimeFormatINT); //lese international s := DateTimeToStr(dt, DateTimeFormatDE); //erstelle deutsch-typsch Delta := (ItemHeight div 2) - (Canvas.TextHeight(Items[Index]) div 2); Canvas.TextRect(Rect, Rect.Left + 2, Rect.Top + Delta, s); end; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:13 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