![]() |
Grundlegende Frage zur Strukturierung von Records und tList
Schönen guten Abend,
ich war früher viel in einem anderen Forum unterwegs, welches aber leider geschlossen wurde. Aus dem Grund mache ich jetzt meine ersten Versuche hier auf Delphi-Praxis. Mögliche Fehlbedienungen möge man mir nachsehen ;-) Ich habe ein seit längerem andauerndes Projekt, bei dem ich eine Anzahl von Strings verwalte. Jedes Zeichen eines Strings steht für Objekte (Amino- oder Nukleinsäuren) und ich führe darauf Wiederholungs- und Ähnlichkeitsanalysen durch. Jeder String ist ein Teil eines Records und trägt zusätzlich eine Feld für einen Namen. Die Strings verwalte ich in einer tList. Die grundlegende Idee habe ich im folgenden einmal skizziert:
Delphi-Quellcode:
Type
pOneSequence = ^tSequence; tSequence = Record Name : String; Data : String; end; tSequenceList = class(TObject) Private fSequenceList : tList; Public Constructor Create; Destructor Destroy; Function NewSequence : Integer; Function SortListAscendingByName : Boolean; // [...] end; Implementation Constructor tSequenceList.Create; Begin Inherited Create; fSequenceList := TList.Create; end; Destructor tSequenceList.Destroy; Var i : Integer; aRecord : pOneSequence; Begin For i := fSequenceList.Count - 1 downto 0 do Begin aRecord := fSequenceList.Items[i]; Dispose (aRecord); fSequenceList.Delete (i); end; Inherited Destroy; end; Function CompareNamesAscending(Item1, Item2: Pointer): Integer; Begin Result := AnsiStrIComp (PChar (pOneSequence(Item1)^.Name), PChar (pOneSequence (Item2)^.Name)); end; Function tSequenceList.SortListAscendingByName : Boolean; Begin Try fSequenceList.Sort (@CompareNamesAscending); Result := True; Except Result := False; end; end; Durch einige Weiterentwicklungen würde ich ein ähnliches System nun gerne für Zahlen und Matritzen anwenden. Dazu ist meine Überlegung, daß ich den Datentyp tSequence erweitere. Leider geht natürlich so etwas nicht:
Delphi-Quellcode:
Als einfachstes Rumpfuschen bestünde nun die Option einen klassischen Record zu verwenden und dort alle offenen Arrays drin zu implementieren. Die Teile die genutzt werden würden gesetzt, der Rest auf die Länge Null minimiert. Letztlich geht es mir um die Frage des Datendesigns und wie man es am sinnigsten implemetieren kann.
tSequenceType = (seqNumericList = 0,
seqNumericArray = 1, seqString = 2); t1dVariantArrayDouble= Record Title : String; RowTitles : Array of String; Cells : Array of Double; end; t2dVariantArrayDouble= Record Title : String; RowTitles : Array of String; ColTitles : Array of String; Cells : Array of Array of Double; end; tSequence = Record Name : String; Case SeqType : tSequenceType of seqNumericList : (Data : t1dVariantArrayDouble); seqNumericArray : (Data : t2dVariantArrayDouble); seqText : (Data : String); end; Es ist mir klar, daß ich viel ändern muss, wenn ich zukünftig auch solch unterschiedlichen Elemente bearbeiten will, aber die Frage ist nun wie geht man da am Besten ran. Hierzu bin ich nun brennend dran interessiert, was andere Leute für Lösungsansätze wählen würden. Da die Funktionalität des Programms in der letzten Zeit deutlich an Umfang zugenommen hat, ist damit zu rechnen, daß später evtl. noch andere Datentypen in der Liste untergebracht werden können. Jetzt ist noch so einer der letzten Punkte, daß ich 'Altlasten' ausbügeln kann. Momentan erscheint mir am sinnigsten, daß man hier evtl. zwei Klassen aufbaut. Die eine, die Daten verwaltet, die andere die Objekte der ersten Klasse verwaltet. Oder hat noch jemand andere Ideen? Falls ja, wie würde sich das dann äußern, bzw. wie würde es dann aussehen. Ich bin momentan in der verzwickten Lage, das ich eines dieser als 'Quick'n'dirty' geplanten Programme versuche auf eine evtl. zukunftsweisende Richtung umzustellen (auch wenn es bisher nur umsonst für einen kleinen Nutzerkreis zur Verfügung gestellt ist...) Liebe Grüße, bin gespannt auf Ideen und Umsetzungsvorschläge... BoolString; |
Re: Grundlegende Frage zur Strukturierung von Records und tL
Also abgesehen davon, dass du auch Klassen verwenden könntest anstatt den Records, wo liegt jetzt dein Problem? An welcher Stelle möchtest du wie die Zugriffe auf die Felder vereinfachen?
|
Re: Grundlegende Frage zur Strukturierung von Records und tL
Klassen währen wohl gut.
und sowas geht eh nich,
Delphi-Quellcode:
da mann dynamische Arrays und Strings nicht in varianten Recordteilen verwenden darf/kann ... da hat Delphi was dagegen, wegen nich eindeutiger Speicherverwaltung.
Case SeqType : tSequenceType of
seqNumericList : (Data : t1dVariantArrayDouble); seqNumericArray : (Data : t2dVariantArrayDouble); seqText : (Data : String); end; |
Re: Grundlegende Frage zur Strukturierung von Records und tL
Hallo Sirius,
mein Problem liegt eigentlich eher darin, daß ich am Überlegen bin, was das sinnvollste ist. Es gibt hierbei ja durchaus die eine oder andere Option, wie man an eine Lösung herangeht. Einige der Lösungen sind allerdings für mögliche spätere Erweiterungen nicht unbedingt die Besten. Es geht also weniger um ein vereinfachen von Zugriffen, sondern vielmehr um all Meine Stärke liegt eher in der Entwickelung der Algorithmen/Berechnungen als im Klassendesign. Aus dem Grund würde mich interessieren, wie andere hier herangehen und was deren Meinung nach Vor- und Nachteile unterschiedlicher Ansätze sind... @himitsu: Ja, in varianten Teilen eines Records kann man keine varianten Arrays unterbringen. In klassischen Records ginge das schon. Mir fehlt bisher die Vorstellung, wie man am Besten eine entsprechende Klasse aufbaut, die die einzelnen Datensätze kapselt. Ebenso wie diese dann in einer tList am Besten verwaltet wird und man sinnvoll über eine Schnittstelle zugängig macht. Hoffe ich hab mich nicht zu konfus ausgedrückt... BoolString; |
Re: Grundlegende Frage zur Strukturierung von Records und tL
du kannst die ja eine Basisklasse mit den nötigen (grundlegenden) Schnittstellen erstellen und von dieser dann jeweils eine Klasse für NumericList, NumericArray und String davon ableiten.
|
Re: Grundlegende Frage zur Strukturierung von Records und tL
Und dann kannst du auch eine TObjectList anstatt TList nehmen.
|
Re: Grundlegende Frage zur Strukturierung von Records und tL
Besten Dank für die bisherigen Anregungen!
Ich habe mich gestern Abend einmal hingesetzt und versucht etwas entsprechendes aufzubauen. Dazu sind nun einzelne Klassen für unterschiedliche Datenobjekte entstanden. Nach der Anregung von Sirius habe ich eine ObjectList zur Hälterung der einzelnen Datenobjekte verwendet. Leider muss ich aber feststellen, daß meine Erfahrungen im Klassendesign mangelhaft sind und ich somit an einigen Punkten nicht weiterkomme. Hier ein Ausschnitt aus meinem Versuch, der die relevanten Teile beinhaltet:
Delphi-Quellcode:
Type
tDataSetType = (seqString = 0, seqValueList = 1, seqMatrix = 2, seqTable = 3 ); tDataTypeName = String; tDataTypeString = String; tDataTypeValueList = Array of Double; t2dVariantArrayDouble = Record Title : String; RowTitles : Array of String; ColTitles : Array of String; Cells : Array of Array of Double; end; tDataObjectString = Class (tObject) Private fName : tDataTypeName; fData : tDataTypeString; Function CountDataChars : Longint; Public Property Name : tDataTypeString read fName write fName; Property Data : tDataTypeString read fData write fData; Property Count : Longint read CountDataChars; end; tDataObjectMatrix = Class (tObject) Private fName : tDataTypeName; fData : t2dVariantArrayDouble; Function CountDataRows : Longint; Function CountDataCols : Longint; Public Property Name : tDataTypeString read fName write fName; Property Data : t2dVariantArrayDouble read fData write fData; Property Rows : Longint read CountDataRows; Property Cols : Longint read CountDataCols; end; tDatasets = Class (tObject) Private fDatasetList : tObjectList; Public Constructor Create; Destructor Destroy; Function New (SequenceType : tDatasetType) : Integer; Function Get (aIndex: Longint; Var aDataObject: tDataObjectString) : Boolean; overload; Function Get (aIndex: Longint; Var aDataObject: tDataObjectValues) : Boolean; overload; Function Get (aIndex: Longint; Var aDataObject: tDataObjectMatrix) : Boolean; overload; end; Implementation // --------------------------------- Datenobjekt tDataObjectString Function tDataObjectString.CountDataChars : Longint; begin Result := Length (fData); end; // --------------------------------- Datenobjekt tDataObjectMatrix Function tDataObjectMatrix.CountDataRows : Longint; Begin Result := High(fData.Cells) + 1; end; Function tDataObjectMatrix.CountDataCols : Longint; Begin if CountDataRows > 0 THen Result := High(fData.Cells [0]) + 1 Else Result := 0; end; // --------------------------------- Liste der Datenobjekte Constructor tDatasets.Create; Begin Inherited Create; fDatasetList := tObjectList.Create; fDatasetList.OwnsObjects := True; end; Destructor tDatasets.Destroy; Var aObject : Integer; Begin For aObject := fDatasetList.Count - 1 downto 0 do Begin fDatasetList.Delete (aObject); end; Inherited Destroy; end; Function tDatasets.New (SequenceType : tDatasetType) : Integer; Begin Try Case SequenceType of seqString : fDatasetList.Add (tDataObjectString.Create); seqValueList : fDatasetList.Add (tDataObjectValues.Create); seqMatrix : fDatasetList.Add (tDataObjectMatrix.Create); end; Result := fDatasetList.Count; Except Result := -1; end; end; Function tDatasets.Get (aIndex: Longint; Var aDataObject: tDataObjectString) : Boolean; Begin Result := False; If (aIndex >=0) And (aIndex < fDatasetList.Count) THen Begin If (fDatasetList.Items [aIndex] is tDataObjectString) THen Begin aDataObject := (fDatasetList.Items [aIndex] as tDataObjectString); Result := True; end; end; end; Function tDatasets.Get (aIndex: Longint; Var aDataObject: tDataObjectMatrix) : Boolean; Begin Result := False; If (aIndex >=0) And (aIndex < fDatasetList.Count) THen Begin If (fDatasetList.Items [aIndex] is tDataObjectMatrix) THen Begin aDataObject := (fDatasetList.Items [aIndex] as tDataObjectMatrix); Result := True; end; end; end; Somit kann ich auch schön Datensätze erzeugen und diese per Index in der Klasse tDatasets referenzieren. Da ich nun aber variante Arrays benötige, habe ich ein Problem mit dem Zugriff. Ich habe allerdings die Vermutung, daß die Probleme meinem derzeitigen Erfahrungsschatz zuzuordnen sind.
Delphi-Quellcode:
Var DatasetList : tDatasets;
anObject : tDataObjectMatrix; Begin DatasetList := tDatasets.Create; DatasetList.New (seqMatrix); If DatasetList.Get (0, anObject) THen Begin anObject.Name := 'Testobjekt'; anObject.Data.Title := 'Darin enthaltene Matrix'; // Der linken Seite kann nichts zugewiesen werden SetLength ((anObject as tDataObjectMatrix).Data.Cells, 2, 2); // Konstantenobjekt kann nicht als Var-Parameter weitergegeben werden end; end; Wie müsste man die Klassen sauber aufbauen, damit ich mit den varianten Elementen arbeiten kann? Auch wenn es natürlich viel Material ist und sich vielleicht nicht gerade als Einstiegstopic in ein neues Forum eignet, wäre ich über konkrete Tipps dankbar ;-) Es geht mir nicht darum, daß ich hier etwas fertiges haben möchte. Aber momentan wäre ein Schubser in die richtige Richtung sehr hilfreich. Bisher habe ich überwiegend nur fertige Klassen ein wenig erweitert. Ich denke, ich muss mich da jetzt tatsächlich endlich mal reinfummeln. Liebe Grüße und besten Dank Jan PS: Falls der Hintergrund interessiert: ich würde gerne ein kleines Softwareprojekt aufbohren und um Berechnungen für numerische Daten erweitern; ![]() [...] |
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:16 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 by Thomas Breitkreuz