![]() |
Listboxen vergleichen
Hallo,
ich sitze in letzter Zeit an einem Program, dass Backup löschen soll, es soll immer ein Backup pro Tag behalten werden. Das sortieren klappt so weit, heisst ich weiss welche Backups ich behalten will, dafür habe ich zwei Listboxen, eine die die zubehaltenden Backups anzeigt[Listbox1] und eine die alle Backups anzeigt[Listbox2]. Das Problem besteht darin, dass ich es nicht hin bekomme heraus zufinden welches Backup jetzt gelöscht werden soll oder nicht. Hier ist der Code den ich dafür vorgesehen hatte:
Delphi-Quellcode:
Vielen Dankt im vorraus !
for I := 0 to Listbox2.Items.Count-1 do
begin for Ia := 0 to Listbox1.Items.Count-1 do begin if NOT (Listbox2.Items[i]=Listbox1.Items[ia]) then begin //Die sollen gelöscht werden end; end; end; |
AW: Listboxen vergleichen
Versuchs doch mal mit Listbox1.Items.IndexOf(Listbox2.Items[i])
Result ist gleich der Index des gesuchten Elements, oder, wenn es diese nicht gibt, -1 Das hilft dir bestimmt weiter. |
AW: Listboxen vergleichen
Meinst du so ?
Delphi-Quellcode:
if NOT (Listbox1.Items.IndexOf(Listbox2.Items[i])=-1) then
|
AW: Listboxen vergleichen
Oder mit ein bischen Quelltext:
Delphi-Quellcode:
Hier gehe ich die Listbox1 von unten nach oben durch. Wenn das jeweilige Element in der Listbox2 nicht vorhanden ist, dann wird das Backup gelöscht. Ist das Löschen erfolgreich, wird das Element aus Listbox1 auch auch gleich entfernt.
for i := Listbox1.items.count-1 downto 0 do begin
if Listbox2.items.indexof(Listbox1.items[i])=-1 then begin if DeleteFile(Listbox1.items[i]) then Listbox1.delete(i); end; end; |
AW: Listboxen vergleichen
Zitat:
Delphi-Quellcode:
ist aber im Grunde das gleiche. Möglicherweise ist der verzicht auf NOT etwas schnellen, aber das wird ggf. auch vom Compiler optimiert, wäre aber auch bei dieser Operation zu vernachlässigen, da die Rechner heute so schnell sind, dass das eh nicht auffallen würde. (Meine Meinung ;-) )
if Listbox1.items.IndexOf(Listbox2.Items[i])>-1 then
|
AW: Listboxen vergleichen
Zitat:
das "downto" würde ich diese Stelle verwenden, weil wenn du es anders herum macht, also "for i:=0 to Listbox1.items.count-1" dann kommst du ja irgendwann an eine Stelle, wo aus Listbox1 ein Element löscht. Nach dem Löschen ist Listbox1.Items.count ja kleiner, und die Schleife will am Ende irgendwann auf ein Element zugreifen, was ja gar nicht mehr existiert. Dann hagelt es eine Exception. |
AW: Listboxen vergleichen
Du kannst das Problem reduzieren, indem du nicht die Listboxen anschaust sondern die Items[] Properties.
Dabei handelt es sich um TStrings-Objekte. (bzw. von der Klasse TStrings abgeleitet). Also willst du zwei Stringlisten "vergleichen". Vergleichen ist auch nicht das richtige Wort, sondern es dreht sich eher um ![]() Man kann die Schnittmenge zweier Stringlisten bilden oder die Vereinigungsmenge oder auch die Restmenge (Menge A ohne B). siehe auch Code-Library: ![]() Wenn man mal das Prinzip der Mengenlehre begriffen hat, dann braucht man nicht im Nebel stochern sondern kann gezielt das Richtige tun. Und somit hoffe ich, dass alle die hier schnell aus der Hüfte mit etwas Code geschossen haben noch etwas dazulernen. |
AW: Listboxen vergleichen
Habe es jetzt mit einer 3. Listbox versucht und es kommt aber immer noch ein mischmasch raus :(
Delphi-Quellcode:
for i := Listbox1.items.count-1 downto 0 do begin
if NOT (Listbox2.items.indexof(Listbox1.items[i])=-1) then begin //if DeleteFile(Listbox1.items[i]) then Listbox3.Items.Add(Listbox2.Items[i]); end; end; |
AW: Listboxen vergleichen
Zitat:
Und was ist jetzt daran einfacher? |
AW: Listboxen vergleichen
Zitat:
|
AW: Listboxen vergleichen
Zitat:
|
AW: Listboxen vergleichen
... kleiner Fehler. Code mal kurz entfernt...
@Captnemo War ja keine Kritik. |
AW: Listboxen vergleichen
Zitat:
Normalerweise müssten jetzt in listbox3 alle Elemente auftauchen, die sowohl in Listbox1 als auch in Listbox2 sind. Denk aber daran, dass auch groß und kleinschreibung unterschieden wird. Ggf. noch ein lowercase() einbauen. |
AW: Listboxen vergleichen
Ich grübe grade darüber nach was ich von den 3 Mengenoperationen verwenden muss, aber ich denke,
wenn ich
Delphi-Quellcode:
nehmen würde müsste es doch gehen oder ?
DifferenceStrings(Listbox2.Items,Listbox1.Items,Listbox3.Items)
|
AW: Listboxen vergleichen
Zitat:
Okay, aber am ende kommt ja alles auf das gleiche raus. |
AW: Listboxen vergleichen
Okey jetzt gehts, O.o komisch...
Aber danke an alle ! ..war schon wieder am verzweifeln.. |
AW: Listboxen vergleichen
Zitat:
Die von dir gestellt Aufgabe ist so einfach, dass du dir selbst einen Gefallen tust, wenn diesen zweizeiler selber entwirfst, und am ende auch verstehst, wo wie ich und popov es dir vorgeschlagen haben. |
AW: Listboxen vergleichen
Ja,okey habe aber auch schon lange nichts mehr mit Delphi gemacht...
Habs jetzt auch so hin bekommen. |
AW: Listboxen vergleichen
Ja, manchmal beißt man sich an einfachsten Sachen fest. Kein Problem.
|
AW: Listboxen vergleichen
Zitat:
Mit "unschön" meine ich jetzt z.B. das fehlende BeginUpdate/EndUpdate. Unschön ist natürlich auch keine Unter-Funktion/Prozedure zu verwenden. |
AW: Listboxen vergleichen
Zitat:
Wenn ich tatsächlich nur aus einer Liste alle in einer zweiten Liste vorhanden Elemente löschen will, dann reicht mir ja im Grund ein Zweizeiler.
Delphi-Quellcode:
Gut, jetzt sind's 3 Zeilen ;-)
for i:=listbox1.items.count-1 downto 0 do
if listbox2.items.indexof(listbox1.Items[i])>-1 then Listbox1.items.delete(i); Diese jetzt doch relativ simple Aktion extra noch in eine Funktion zu packen, die dann wiederum eine weitere StringListe benötigt, um dann am Ende das gleich zu erhalten, was hinterher in Listbox2 stehen sollte, halte ich für unsinnig. Zum einen wird der Code dadurch nicht unbedingt überichtlicher, und zum zweite muß ich hinterher dann auch noch die Listbox2 neu aufbauen. Außerdem kann ich so die auszuführenden Aktionen auch gleich mit in die Schliefe packen. Die einzigen Gründe, die mir dazu einfallen würden, wären: 1. Ich will die Listboxen erst verändern, wenn ich alle Aktionen, die das Ergebnis betreffen, ausgeführt wurden 2. Ich will die Differenz noch mehrmals verwenden. 3. Ich will dem Benutzer erst eine Liste aller betroffenen Elemente als Vorschau anzeigen. Aus deiner ursprünglichen Frage schließe ich aber, dass du lediglich die Differenzelemente aus der Liste löschen und die backups löschen willst. Dafür würde ich mir nicht erst eine Funktion anlegen, weil ich die ja nur einmal benötige, und ich dadurch an dieser Stelle noch nicht einmal Code gespart habe. Denn: Ich muß mir extra noch ein StringList anlegen, ich muß natürlich die Funktion aufrufen, ich muß hinterher meine neue Stringlist (wieder mit einer Schliefe) verarbeiten, und ich muß die Listbox1 trotzdem aktualisieren. Und den zusätzlich code für die Funktion brauch ich auch noch. also habe ich durch die Funktion min. 10-15 Zeilen mehr Code. Bei aufwendigeren Funktionen macht das aber durchaus sinn, oder wenn es der Übersichtlichkeit dient. |
AW: Listboxen vergleichen
@Captnemo: irgendwie fällt es dir schwer die Listboxen loszulassen und nur in Listen zu denken.
Man kann Liste B von A abziehen indem man das Ergebnis in C schreibt oder man macht es so wie du quasi in-place:
Delphi-Quellcode:
Und selbst wenn diese Procedure nur ein Einziges mal benützt wird, ist das Ergebnis doch besser lesbar und sogar schneller.
// Berechne A=A-B
procedure SubstractStringsInplace(A,B:TStrings); var i:Integer; begin for i:=A.Count-1 downto 0 do if B.IndexOf(A[i])>=0 then A.delete(i); end; ... SubstractStringsInplace(Listbox1.Items, Listbox2.Items); Schneller deswegen weil man nicht ständig auf die Listboxen zugreift, sondern mit den Items, also den TStrings-Objekten arbeitet. Noch schneller würde es wenn man zusätzlich A.BeginUpdate & A.EndUpdate verwendet. Auch kleine Funktionen/Proceduren sind wichtig und wertvoll!! |
AW: Listboxen vergleichen
Zitat:
Mal ehrlich, wenn ich von 10 Backups nur 3 Behalten will, wieviele Millisekunden willst du da durch irgendwelche Funktionen sparen? Besser lesbar.....sehe ich anders. Wenn überhaupt, dann genauso lesbar. Wir reden hier von 3-5 zeilen code. Was bitte soll denn da unübersichtlich sein? Und was ist Listbox1.Items....TString-Objekte. Ergo wird der Zugriff auf diese nicht schneller oder langsamer sein, als selbst erzeugte. Hilfeauszug: Zitat:
Wegen mir kann jeder seine kleinen Schliefen in Funktionen auslagern, wenn er das toll findet. Aber mit Übersichtlichkeit hat das in diesem Fall nun wirklich nichts zu tun. Eher im Gegenteil. Wenn ich jede Kleinigkeit in Funktionen auslagere, dann hab ne Unit mit hundeten Funktionen, die alle nur 3-5 Zeilen lang sind. Da steigt ja dann keiner mehr durch. Damit meine ich jetzt nicht, Spagetti-code zu programmieren. Funktionen ja, aber nur wenn's sinn macht. Besser ist es, vernüftige Kommentare zu setzen. |
AW: Listboxen vergleichen
@Captnemo
Ich würde dir mal einen Blick auf die Pattern empfehlen, da kann man eine Menge lernen wie und warum ;) ![]() |
AW: Listboxen vergleichen
Zitat:
Genau das sag ich ja. Wenn man einen bestimmten Ablauf an verschieden Stellen benötigt mach es ja sinn, das ganze in eine Funktion zu packen. Mach ich auch nciht anders. Und wenn möglicherweise aufwendige Abläufe nötig sind, versuche ich das auch in ein Funktion zu packen, damit die Übersichtlichkeit gegeben bleibt. Aber weder das eine, noch das andere ist hier ja gegeben. Natürlich kann mal letztlich alles vereinheitlichen und in Funktionen realisieren. Nur war das nicht die Frage des Threads. Er wollte wissen, wie er bei zwei Listboxen zu seinem Ergebnis kommt, und das habe ich ihm gesagt. Ob er dieses Wissen nun nimmt, um damit das gleiche über TStrings in einer Funktion zu machen, ist ja ihm überlassen. Die prinzipielle Vorgehenweise ist dabei ja letztlich das gleiche. |
AW: Listboxen vergleichen
Zitat:
Ich zitiere mal aus dem Buch Clean Code: A Handbook of Agile Software Craftsmanship von Robert C. Martin et al. Zitat:
|
AW: Listboxen vergleichen
Zitat:
|
AW: Listboxen vergleichen
Zitat:
Zitat:
Man muss diese Empfehlungen natürlich aus der Sicht eines professionellen Softwareentwicklers sehen. Der Hobbyprogrammierer versteht nicht, weshalb es besser ist, hunderte kleine Funktionen zu haben, als kommentierten Code, der ohne sie auskommt: Es geht um Lesbarkeit. Ist ein Code lesbar (und kann ich ihn meinem Kollegen vorlesen bzw. er den Code selber lesen), dann ist er verständlich. Und zwar ohne Rücksprache oder das im Code Kommentare verstreut sind. Lesbarer Code ist einfach (KISS). Einfacher Code ist robust und erweiterbar. |
AW: Listboxen vergleichen
Auch ich arbeite mit Funktion.
Die Frage des Threaderstellers war es, wie er zwei Listbox so vergleichen kann, dass er sein gewünschtes Ergibnis erhält. Ich habe ihm eine Antwort gegeben, die ihm bei der Lösung seines Problems hilft. Punkt. Ich halte nichts davon, jemandem dann eine Unit rein zu kopieren, die ihm Funktionen für ein so simples Problem zur Verfügung stellt, die dann ohne eigenes Zutun das gewünschte Resultat bring, ohne verstehen zu müssen, was da eigentlich passiert. Einfach reinkopieren und fertig. Das das keiner Verstehen will....okay. Deswegen lass ich mich hier nicht als "hoffnungslos" betiteln. Jedenfalls hab ich jetzt keine Bock mehr hier jemandem einen Lösungsvorschlg zu posten. Damit ist dieser Thread für mich erledigt. |
AW: Listboxen vergleichen
PS: Die Konstante -1 ergibt meistens soeinen unschönen Assemblercode und der Vergleich darauf ist auch nicht so schön.
Wenn man anstatt mit dem "Fehler" zu vergleichen, auf die korrekten Werte prüft, sieht es gleich viel hübscher aus. z.B. bezüglich
Delphi-Quellcode:
oder
if IndexOf(...) = -1 then
Delphi-Quellcode:
:
if not (IndexOf(...) = -1) then
Delphi-Quellcode:
für "ist nicht drin" (OK, es sei denn man hat eine "sprechende" Konstante für den Fehlercode)
if IndexOf(...) < 0 then
und
Delphi-Quellcode:
für "ist drin".
if IndexOf(...) >= 0 then
Eine positive Logik klingt auch meistens freundlicher und wenn man sich durchgehend vorwiegend auf eine Logik bezieht, ist der Code IMHO oftmals auch schneller verständlicher, da man weniger überlegen muß. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:07 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