![]() |
Dubikate in TStringGrid anzeigen (den Rest rausschmeißen)...
Ich glaube ich habe da mal eine kleine Denkblokade oder so. Normalerweise ist es ja so, dass man versucht Dublikate zu entfernen. Aber bei mir ist es andersrum, denn die Einträge, die nicht doppelt sind, sind in Ordung und die will ich aus dem StringGrid schmeißen. Genauer gesagt geht es nur um eine Spalte des StringGrids, die nur Integerwerte enthält und sortiert ist.
Es ist wahsrcheinlich total banal udn ich komme einfach nicht drauf :wall: . Also, wäre nett, wenn mir einer helfen würde *Hundeblick* |
Re: Dubikate in TStringGrid anzeigen (den Rest rausschmeißen
Hallo
Du kannst dir die Cols-eigenschaft vom Grid zu Hilfe nehmen, sind auch tstrings. Durchlauf sie vom ende und prüf mit indexof, ob der Wert nochmal in der Spalte enthalten ist. Wenn indexof dir die aktuelle Position zurückgibt, ist der Eintrag nicht doppelt drin. Liefert indexof einen kleineren Wert, steht der gleiche Eintrag schon mal vorher in der Liste, dann löschen und nochmal suchen. Mfg Frank |
Re: Dubikate in TStringGrid anzeigen (den Rest rausschmeißen
Hai yankee,
hier noch eine alternative Methode (zum testen habe ich eine ListBox genommen):
Delphi-Quellcode:
Ich durchlaufe von unten nach oben die Einträge von count -2 (vorletzter) bis 1 (zweiter) und prüfe ob der Eintrag davor oder danach gleich dem aktuellen ist. Wenn dies nicht zutrifft lösche ich den aktuellen.
procedure TForm1.Button1Click(Sender: TObject);
var ndx: integer; begin with ListBox1 do begin for ndx := Count - 2 downto 1 do begin if not ((Items[ndx] = Items[ndx + 1]) or (Items[ndx] = Items[ndx - 1])) then begin Items.Delete(ndx); end; end; // Schleifen ende if not (Items[0] = Items[1]) then // erster <> zweiter begin Items.Delete(0); end; if not (Items[Count-1] = Items[Count-2]) then // letzer <> vorletzer begin Items.Delete(Count-1); end; end; end; Ganz zum schluss prüfe ich noch ob der erste = dem zweiten ist bzw. der letze = dem vorletzten. Aber die Methode von Keldorn ist auch sehr elegant :stupid: |
Re: Dubikate in TStringGrid anzeigen (den Rest rausschmeißen
Die von Frank beschriebene Methode kenne ich aus meiner code library:
Delphi-Quellcode:
Grüße vom marabu
procedure KeepDuplicates(sl: TStringList; allDuplicates: boolean = false);
var i, dist: integer; begin if not sl.Sorted then sl.Sort; for i := sl.Count - 1 downto 0 do begin dist := i - sl.IndexOf(sl[i]); if dist > i then Continue; if (dist = 0) or (not allDuplicates and (dist > 1)) then sl.Delete(i); end; end; |
Re: Dubikate in TStringGrid anzeigen (den Rest rausschmeißen
Liste der Anhänge anzeigen (Anzahl: 1)
Hai marabu,
kann es sein das dein Code einen Fehler hat? Wenn ich diesen mit meiner Listbox verwende (vorher alles in eine SL kopier). stimmt das Ergebniss nicht mit der Aufgabe überein. :gruebel: Ich hänge mein Testprojekt mal an. |
Re: Dubikate in TStringGrid anzeigen (den Rest rausschmeißen
Kann ich mich bei einem TStringList.IndexOf denn darauf verlassen, das bei doppeltem Vorkommen immer der erste Eintrag gefunden wird, vor allen Dingen, wenn die TStringList.sorted = True ist? Ich weiss, eine ketzterische Frage.
Um auf Nummer Sicher zu gehen, würde ich mir die Mühe machen, das IndexOf durch eine kleine eigene Routine ersetzt, die prüft, ob ein Wert in der Unterliste (0..n) vorhanden ist, oder nicht. Bei einer sortierten Liste (wie in deiner Codelibrary) liegen Duplikate naturgemäß nebeneinander, insofern erübrigt sich eine Suche mit IndexOf: Entweder ist mein Vorgänger mit mir identisch, oder eben nicht. Desweiteren sollten Duplikate nur 1x auftreten. Hier also mein Versuch (er erstellt aber eine zweite Liste, die die doppelten Einträge enthält):
Delphi-Quellcode:
Procedure FindDuplicates (aList, aDuplicates : TStringList);
Var i : Integer; sSample : String; Begin aList.Sort; i := 1; sSample := aList [0]; While i<aList.Count - 1 do begin j := i; While aList[i] = sSample do inc (i); if j< i - 1 then aDuplicates.add(sSample); sSample := aList[i]; End; End; |
Re: Dubikate in TStringGrid anzeigen (den Rest rausschmeißen
Zitat:
Das mit dem sortieren geht sicher auch, aber es ist nicht unbedingt immer gewünscht, das nach dem Löschen der doppelten Einträge die Liste auch noch sortiert ist und die ursprüngliche Reihenfolge verloren ist. |
Re: Dubikate in TStringGrid anzeigen (den Rest rausschmeißen
Sharky, du hast tatsächlich einen Fehler in meiner Routine gefunden und alzaimar hat ihn korrekt erklärt. Vielen Dank euch beiden.
Delphi-Quellcode:
Die Routine stammt aus einer Sammlung von Mengenoperationen auf Strings. Benutzt habe ich sie nie, aber der zugehörige Testcode erzeugte seine Testdaten so:
procedure KeepDuplicates(sl: TStringList; allDuplicates: boolean = false);
var i, j, dist: integer; begin if not sl.Sorted then sl.Sort; for i := sl.Count - 1 downto 0 do begin j := i; // "j := sl.IndexOf(sl[i])" würde einen sporadischen Fehler produzieren while (j > 0) and (sl[j - 1] = sl[j]) do Dec(j); dist := i - j; if (dist = 0) or (not allDuplicates and (dist > 1)) then sl.Delete(i); end; end;
Delphi-Quellcode:
Was soll ich sagen, damit produzierte der Code in den ersten Durchläufen korrekte Ergebnisse. Ich werde meinen Testcode wohl etwas verfeinern müssen...
for i := 1 to 20 do
sl.Add(IntToStr(Random(30))); Verlegene Grüße vom marabu PS: Fehler nach Hinweis von alzaimar korrigiert |
Re: Dubikate in TStringGrid anzeigen (den Rest rausschmeißen
Wenn Du bei einer TStringList Sorted auf True setzt, dann wird beim IndexOf nicht sequentiell, sondern binär gesucht (binarysearch). Das findet aber nur irgendeinen Eintrag, aber nicht unbedingt den Ersten. Beispiel: Liste = (1,2,2,2,3). Suche nach 2 liefert im ersten Durchgang einen Treffer, nämlich l[2] ='2', das ist aber nicht das erste Auftreten. Deshalb ist die Verwendung des Suchergebnisses als Kriterium für doppelte Einträge bei sortierten Stringlisten (Sorted = True) nur bedingt anwendbar. Im Beispiel vom marabu umgeht er das, indem er von hinten an die Sache rangeht.
Noch eine Anmerkung zum marabu-Verfahren: Man kann die Zeile
Delphi-Quellcode:
durch
j := sl.IndexOf (sl[i]);
Delphi-Quellcode:
ersetzen, da die Liste sortiert ist und j danach sowieso auf das erste Element gesetzt wird.
j := i;
|
Re: Dubikate in TStringGrid anzeigen (den Rest rausschmeißen
Hallo alzaimar,
man KANN nicht nur IndexOf() durch die Gleichsetzung von j mit i ersetzen, man MUSS es sogar. Habe ich auch so in meiner library geändert und doch den falschen Code hier bereit gestellt. Muss unbedingt ein Seminar zum Thema Copy & Paste besuchen... Nochmal danke marabu |
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:06 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