![]() |
Delphi-Version: XE2
String in TObjectList suchen
Guten Morgen z'sammen,
ich arbeite und lerne zur Zeit mit Delphi. Bei allen bis heute auftretenden Problemen, hat mir diese Community super geholfen und ich konnte meine Fehler immer finden und beseitigen, doch heute bräuchte ich mal Hilfe. Dazu schildere ich am besten mal mein Problem so gut wie es geht: Ich habe ein Memofeld in den ich Text schreibe. Die einzelnen Wörter werden ausgelesen und in einen String geschrieben - natürlich nicht alle auf einmal. Sobald also ein vollständiges Wort in meinem String ist, soll in meiner TObjectList gesucht werden, ob es bereits vorhanden ist und wenn es das nicht ist, soll es mit einem Counter hinzugefügt werden. Es scheitert bei mir nicht an dem Hinzufügen, sondern an dem Abgleich, weil ich dort eine OutOfRange-Exception bekomme und ich mit den Lösungen im Internet nicht wirklich viel anfangen konnte. Ich schicke euch mal meinen jämmerlichen Ansatz, wie ich versuche den Abgleich zu machen. <embarassed>
Code:
__________________________________________________ __________________________________________________ _______________________________________________
repeat
if TCharacter.isletter(sEingabe[iIndex]) then // Solange das aktuelle Zeichen begin // ein Buchstabe ist, sWort := (AnsiLowerCase(sWort) + sEingabe[iIndex]); // soll dieser zu sWort gefügt werden. end else begin iCounter := 0; if sWort <> '' then // Wenn es ein anderes Zeichen ist begin if List.Count = 0 then begin iAnzahl := 1; List.Add(TWort.create(AnsiLowerCase(sWort), iAnzahl)); // Sobald es ein anderes Zeichen ist, soll sWort der TObjectList hinzugefügt werden // Erhöht die Häufigkeit um einen sWort := ''; end else begin repeat if sWort = List[iCounter].sWort2 then <--------------- Hier meckert er! begin List[iCounter].iAnzahl := List[iCounter].iAnzahl + 1; // Erhöht die Häufigkeit um einen sWort := ''; iCounter := List.Count - 1; end else begin if List[List.Count - 1].sWort2 = '' then begin break; end else inc(iCounter); end; until iCounter = List.Count - 1; end; if sWort <> '' then begin iAnzahl := 1; List.Add(TWort.create(AnsiLowerCase(sWort), iAnzahl)); // Sobald es ein anderes Zeichen ist, soll sWort der TObjectList hinzugefügt werden // Erhöht die Häufigkeit um einen sWort := ''; end; end; end; inc(iIndex); until iIndex = Length(sEingabe) + 2; (Verzeiht mir, wenn ich nicht die richtige Implementation gewählt habe, mein Browser spinnt gerade irgendwie. Ich kann nichtmals Smileys setzen...) Also zur Erklärung: Der Obere Teil ist ja einfach nur das Auslesen und gucken, ob es ein Buchstabe ist oder nicht. Danach soll er dann, weil ja zu Beginn noch kein Element in der List ist, das erste Wort ohne Abgleich reinschreiben. Sobald List.Count aber nicht mehr 0 ist, also ein Element vorhanden ist, soll er den neuen String mit den Elementen in der Liste vergleichen und bei einem Fund den Zähler für dieses Wort erhöhen. Und wenn das Wort halt nicht drin ist, dann soll er es ganz normal hinzufügen - so weit der Plan. Ich hoffe ich konnte das gut genug schildern und bedanke mich schonmal für eure Hilfe. Gruß Jan |
AW: String in TObjectList suchen
Der Index wird bei 0 beginne, dann ist der höchste Index Count-1
|
AW: String in TObjectList suchen
Hallo mkinzler,
das fiel mir beim durchlesen auch ebengerade auf, ich hatte die -1 da eigentlich schon drin stehen, war jetzt selbst verwirrt... Fehler gelangt nämlich jetzt an seine alte Position in die Zeile: if sWort = List[iCounter].sWort2 then Gruß Jan |
AW: String in TObjectList suchen
Hier Nicht:
Zitat:
|
AW: String in TObjectList suchen
Wie meinst du "Hier Nicht"? Das ist doch die einzige Stelle, wo es hingehören würde. Mir ist klar, dass die Indexposition bei 0 beginnt, aber außer dieser einen Zeile gäbe es doch sonst keine Möglichkeit.
|
AW: String in TObjectList suchen
List.count ist zb. 3
Der Index ist aber dann von 0..2. Daher ist List.count ein Index den es nicht gibt. Grüße Klaus |
AW: String in TObjectList suchen
Ich muss das glaube ich mal richtig verstehen...
Ich habe eine Liste mit 10 Elementen. Die geht dann von 0 bis 9. Jetzt schreibe ich einen String mit seinem dazugehörigen Integerwert an die erste Stelle, also die 0te. Wenn ich jetzt ein weiteres Element habe, dann soll er das, mit allen Indexpositionen vergleichen, ob der String schon vorhanden ist. Das wollte ich mit iCounter machen, der bei 0 startet und dann sich erhöht bis zu List.Count - 1, also dem höchsten Listenindex. Aber habe ich deinen Fall nicht schon mit der -1 abgedeckt Klaus? |
AW: String in TObjectList suchen
Wäre es nicht einfacher, die Suche in eine eigene Methode auszulagern? Dazu könnte man entweder die Liste erweitern, oder man macht es zur Not von außen.
Delphi-Quellcode:
Gibt diese Funktion -1 zurück, ist das Wort nicht enthalten.
function TWasWeißIch.IndexOfToken(const Token: string): integer;
var idx: integer; begin Result := -1; for idx := 0 to List.Count - 1 do if Token = List[idx].sWort2 then begin Result := idx; break; end; end; |
AW: String in TObjectList suchen
Zitat:
|
AW: String in TObjectList suchen
@mkinzler: Das hatte ich ja verbessert, s. #3
@DeddyH: Ich habe daraus zwar keine eigene Funktion gemacht, aber ich habe das Problem mit einer For-Schleife lösen können. Danke dafür. Er geht das jetzt auch alles richtig durch, doch jetzt wirft er mir während ich das eben gedebuggt habe eine Exception bei meinem Sortieralgorithmus aus...
Code:
Dies ist ebenfalls wieder eine OutOfRange-Exception, aber die verstehe ich nicht so ganz. iHcounter soll eine andere Indexposition haben als iPosition. Ich muss ja schließlich irgendwie die Zahlen zu den Strings sortieren und damit einhergehend vollständige Elemente der TObjectList, oder ist das falsch?
procedure TForm1.Sort(var List: TObjectList<TWort>);
var iCounter, iHcounter, iPosition: integer; Temp: TWort; begin iHcounter := 0; iCounter := 0; while iCounter < High(List[List.Count - 1].iAnzahl) do begin iPosition := iCounter; if iHcounter = High(List[List.Count - 1].iAnzahl) + 1 then begin inc(iCounter); iHcounter := iCounter; end else begin for iHcounter := iCounter + 1 to High(List[List.Count - 1].iAnzahl) do begin if (List[iHcounter].iAnzahl) > (List[iPosition].iAnzahl) then <----------- Siehe hier. // Sortiert die TObjectList nach der Häufigkeit begin Temp := List[iHcounter]; List[iHcounter] := List[iPosition]; List[iPosition] := Temp; end; end; iHcounter := 0; end; end; end; @Edit: Ich verlange nicht, dass ihr mir den kompletten Code vorschreibt, so lerne ich schließlich nicht... Ich brauche nur das Verständnis. Danke. |
AW: String in TObjectList suchen
TObjectList enthält bereits eine
![]() |
AW: String in TObjectList suchen
Schau mal in die Hilfe zu "High()" und dann überleg was "High(List[List.Count - 1].iAnzahl)" deiner Meinung nach zurück gibt.
|
AW: String in TObjectList suchen
@DeddyH: Da stimme ich dir zu, wenn die TObjectList bereits einen Sortieralgorithmus besitzt, werde ich diesen auch nehmen. Bis dato wusste ich davon aber noch nicht.
@DeddyH & Blup: Mit dem High(...) möchte ich sagen, dass er von Beginn der List bis zum höchsten Indexwert durchgeht und sortiert - naja, zumindest habe ich mir das gedacht. |
AW: String in TObjectList suchen
Schau doch bitte mal nach:
![]() |
AW: String in TObjectList suchen
Zitat:
Wenn das so ist, würde ja sowie so dein Vorschlag bezüglich der integrierten Sortiermethode greifen DeddyH. Ich glaube jetzt muss ich mich da erstmal reinlesen, danke für die Hilfe bis hierhin. Gruß Jan |
AW: String in TObjectList suchen
iAnzahl dürfte ja ein Ordinaltyp (Integer?) sein. Also gibt High(List[List.Count - 1].iAnzahl) immer denselben Wert zurück, nämlich den des maximal möglichen für den Typ von iAnzahl, im Falle von Integer also MAXINT.
|
AW: String in TObjectList suchen
Ja das ist richtig, iAnzahl ist ein Integer. Ich wollte aber gar nicht den Maximalwert der Integers wiedergeben, sondern den der TOjectList. :gruebel:
Ich hatte mir jetzt mal, die Sortierfunktion der TObjectList angeschaut, diese ist aber gar nicht anders als meine, kann das sein? Mein Problem liegt daran, dass ich nicht genau weiß, wie ich auf die Richtige "Spalte" der TObjectList zugreife, also auf iAnzahl und danach sortiere und das richtig ausgebe... :glaskugel: |
AW: String in TObjectList suchen
Warum nicht einfach einen
Delphi-Quellcode:
IComparer<T>
![]() Dann kann man ganz simpel mit ![]() |
AW: String in TObjectList suchen
Die Sortierung an sich übernimmt die Liste selbst, Du musst nur die Vergleichsfunktion schreiben, die festlegt, wann ein Item "kleiner" als das andere ist. Diese Vergleichsfunktion kannst Du sogar beim Aufruf als anonyme Methode übergeben. Ungetestet:
Delphi-Quellcode:
Für TComparer musst Du noch die Unit Generics.Defaults einbinden.
List.Sort(TComparer<TWort>.Construct(
function(const Left, Right: TWort): integer begin Result := Left.iAnzahl - Right.iAnzahl; end)); |
AW: String in TObjectList suchen
Also das Vergleichen habe ich ja bereits mit DeddyH's Methode erfolgreich lösen können, die habe ich für meine Belange umgewandelt und integriert.
Einzig diese Sortierfunktion steht mir im Wege. Wobei ich glaube, dass es weniger die Funktion, als mein Verständnis dafür ist. :wall: Zitat:
Ich habe eine Funktion mit zwei Variablen? des Typs TWort. Der Rückgabewert ist ein Integer. Die Rechnung besagt: Links weniger rechts. Bsp.: 4, 9 - Dann sollte jetzt 9 mit 4 getauscht werden. Result = 5. Aber was bringt mir dieses Result? Ich möchte im Enddefekt die nach der Anzahl sortierte Liste in einem weiteren Memofeld ausgeben. |
AW: String in TObjectList suchen
Die Vergleichsfunktion ist ein
![]() ![]() |
AW: String in TObjectList suchen
Also, nach wie vor verstehe ich das nicht ganz. Weder das eine, noch das andere haben mir dabei geholfen.
Ich weiß nicht, wie ich das in meine Code einbinden muss... und je mehr ich mir durchlese, umso verwirrter bin ich. Die dazugehörige Funktion muss ich doch irgendwo niederschreiben, erfolgt das in der class? |
AW: String in TObjectList suchen
Die Funktion steht doch schon in
![]() |
AW: String in TObjectList suchen
Ja ich weiß, ich hatte dazu ja auch was geschrieben. Mein Problem ist einfach das Verständnis dafür.
Es wäre gut, wenn du mir vielleicht das ganze mal an einem Beispiel erklärst, weil ich stehe momentan echt auf dem Schlauch. Ich habe also eine Liste mit zwei Elementen. Das erste hat einen Integerwert von 4 und das zweite Element hat einen Integerwert von 9. Nach deinem Beispiel rechne ich jetzt '9-4' und das Ergebnis ist 5. Was genau bringt mir das aber jetzt? Was sagt diese 5 aus? Diese Funktion muss ich aber doch gewiss irgendwo definieren/hinschreiben in meine Klasse oder nicht? Entschuldigung... Ich bin gerade ziemlich begriffsstuzig. :oops: Gruß Jan |
AW: String in TObjectList suchen
Nicht das Ergebnis, sondern das Vorzeichen ist wichtig.
Ergebnis positiv: 1. Wert ist größer Ergebnis 0: beide Werte gleich Ergebnis negativ: 2. Wert ist größer |
AW: String in TObjectList suchen
Hm ok, das habe ich verstanden. Das funktioniert dann ja wahrscheinlich mit if-Anweisungen, aber wo passiert der eigentliche Tausch? In einer vordefinierten Funktion?
|
AW: String in TObjectList suchen
Der Tausch erfolgt intern in der Sort-Methode der Liste.
|
AW: String in TObjectList suchen
Hm... ich habe das zwar jetzt integriert bekommen, aber es kommen noch mehr Fehler.
Code:
Erstmal, wenn ich in mein erstes Memo "Memo Meme Meme" eintippe, dann erfolgt in der Ausgabe, dem zweiten Memofeld, nur 2x meme, aber "1x memo" fehlt und ich bekomme wieder eine Exception. Ich hatte via Debugger mal in die Liste geschaut und auf Indexposition 0 stand immer noch Memo und auf 1 stand Meme... sollten die nicht getauscht werden? Reingeschaut hatte ich kurz vor der Ausgabe. Danke nochmal für eure Geduld.
List.Sort(TComparer<TWort>.Construct(
function(const Left, Right: TWort): integer begin Result := Left.iAnzahl - Right.iAnzahl; end)); iAusgabe := 0; for iAusgabe := List[iAusgabe].iAnzahl to List[List.Count - 1].iAnzahl do Memo2.Lines.Add(IntToStr(List[iAusgabe].iAnzahl) + 'x ' + List[iAusgabe].sWort2); |
AW: String in TObjectList suchen
Was hat denn der Wert einer Eigenschaft eines Eintrags mit der tatsächlichen Anzahl der in der Liste vorhandenen Einträge zu tun?
|
AW: String in TObjectList suchen
Zitat:
Code:
nur aussagen, dass die Anzahl dem entsprechenden Wort zugeordnet wird. Deine Aussage war doch bestimmt auf die Zeile bezogen, oder?
Memo2.Lines.Add(IntToStr(List[iAusgabe].iAnzahl) + 'x ' + List[iAusgabe].sWort2);
Irgendwie muss ich ja die Werte untereinander in dieses Memofeld schreiben. |
AW: String in TObjectList suchen
Liste der Anhänge anzeigen (Anzahl: 1)
Ich hab mal schnell unter XE eine kleine unkommentierte Demo geschrieben.
|
AW: String in TObjectList suchen
Könntest du für Delphi-Code auch die Delphi-Tags benutzen?
Zitat:
Delphi-Quellcode:
und das verstehe ich irgendwie überhaupt nicht
uses
Math; TComparer<TWort>.Construct( function (const L, R : TWort ) : Integer begin Result := CompareValue( L.iAnzahl, R.iAnzahl ); end );
Delphi-Quellcode:
Nehmen wir an, du hast dort 3 Einträge und der erste Eintrag beinhaltet in iAnzahl eine 5, dann versuchst du auf das 5. Element der Liste zuzugreifen, was es logischerweise gar nicht gibt ... sehr seltsam
iAusgabe := 0;
for iAusgabe := List[iAusgabe].iAnzahl to List[List.Count - 1].iAnzahl do Memo2.Lines.Add(IntToStr(List[iAusgabe].iAnzahl) + 'x ' + List[iAusgabe].sWort2); |
AW: String in TObjectList suchen
Guten Morgen,
@Sir Rufo: Wenn ich den Rückgabewert der Funktion wegnehme, dann meckert er, dass er einen ":" erwartet. Zu folgenden Zeilen:
Delphi-Quellcode:
iAusgabe ist quasi mein Index. Dieser soll vom niedrigsten bis zum höchsten Wert durchlaufen und entsprechend für jeden Indexwert die dort enthaltene Anzahl und das Wort in das Memofeld schreiben. Kann es vielleicht sein, dass ich TObjectLists falsch verstanden habe?
iAusgabe := 0;
for iAusgabe := List[iAusgabe].iAnzahl to List[List.Count - 1].iAnzahl do Memo2.Lines.Add(IntToStr(List[iAusgabe].iAnzahl) + 'x ' + List[iAusgabe].sWort2); Für mich ist das eine Liste von 0 bis n. Da ich Integer- und Stringwerte habe, gibt es zwei Spalten, die nebeneinander sind. Und ich kann doch über einen Indexwert darauf zugreifen oder etwa nicht? |
AW: String in TObjectList suchen
hast du also eigentlich folgendes im Sinn?
Delphi-Quellcode:
for i := 0 to List.Count - 1 do Memo2.Lines.Add(IntToStr(List[i].iAnzahl) + 'x ' + List[i].sWort2); |
AW: String in TObjectList suchen
Das mit ohne dem Rückgabewert war falsch (ist im Beitrag korrigiert).
Nehmen wir an, du hast folgende Liste
Delphi-Quellcode:
von
iAusgabe
Delphi-Quellcode:
läuft.
2..7
Zeige mir doch mal in der Liste die Zeilen mit dem Index
Delphi-Quellcode:
die sind nicht da!
3..7
Verstehen könnte ich
Delphi-Quellcode:
, weil dann läuft
for iAusgabe := 0 to List.Count -1 do
Delphi-Quellcode:
von
iAusgabe
Delphi-Quellcode:
und das sind gültige Index-Werte.
0..2
PS So ein Debugger leistet tolle Arbeit, wenn man den benutzt und sich einfach während des Ablaufs die Variablenwerte anschaut. |
AW: String in TObjectList suchen
Ich bedanke mich für eure Hilfe, die Erklärung zu dem Index der TObjectList hat mir gerade sehr geholfen. Ich lese richtig aus und zähle auch richtig. Danke nochmals. :)
Gruß Jan |
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:39 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