Danke für die super Antworten!
@jfheins
Die Sache mit dem Hoch- und Runtergehen hatte ich mir in der Zwischenzeit auch schon überlegt. So elegant wie Du habe ich es leider nicht, aber es klappt auch bei mir (erprobt mit trial and error).
Wenn ich Deinen Code richtig lese (mit der Betonung auf wenn), dann hat er einen einzigen Haken: Er geht
jedes Mal, wenn ein Fund auftritt, nach oben und nach unten. Wenn man Pech hat, der Benutzer hatte (1) alle Einträge ausgewählt und es gibt (2) jeden Eintrag nur einmal, was (3) zwar nicht gewollt ist, dann bedeutet das selbst im Idealfall immer noch n * 3 (n selbst, 1 oben, 1 unten) Schritte. Mir war auch aufgefallen, dass Du
Clients.Items[I]
immer mit
Clients.Items[J]
statt wie ich mit
Current
vergleichst. Geht das so schneller?
Ich selbst hatte aus diesem Grund bei meinen Überlegungen die For- durch eine While-Schleife ersetzt. Das ganze sieht bei mir jetzt so aus:
Delphi-Quellcode:
I:=0;
While (I < Clients.Count)
Do
Begin
If Clients.Selected[I]
Then
Begin
SendTo[I]:=True;
Current:=Clients.Items[I];
SendList:=SendList + Current + '
, ';
// vor gefundenem Eintrag suchen
J:=Pred(I);
While (J >= 0)
Do
If (Clients.Items[J] = Current)
Then
Begin
SendTo[J]:=True;
Dec(J);
End
Else Break;
// nach gefundenem Eintrag suchen
J:=Succ(I);
While (J < Clients.Count)
Do
If (Clients.Items[J] = Current)
Then
Begin
SendTo[J]:=True;
Inc(J);
End
Else Break;
// nach dem letzten gefundenen Eintrag weiter machen
I:=J;
End
Else Inc(I);
// <- besonders wichtig! Hatte ich erst vergessen und ewig den Fehler nicht gefunden.
End;
Den Vorschlag von
s.h.a.r.k kann ich leider nicht umsetzen, weil ich keine weiteren Daten als die Nummer in der Liste habe. Diese kommt bereits sortiert vom Server. Ein umsortieren der Benutzer lasse ich nicht zu; ist mir einfach zu aufwendung.
ABER: Das bringt mich auf die Idee, wie man es evtl. nochmals verbessern kann. Indem man nämlich die Liste 2 x durchgeht. Beim ersten mal sammelt man "nur" alle die, die markiert sind in einer 2. TStringList, die ebenfalls sortiert ist und keine doppelten Einträge zulässt. Beim 2. Durchlauf vergleicht man dann einfach mit IndexOf(), ob ein entsprechender Eintrag aus der Originalliste auch in der 2. Liste ist.
Es könnte bloß daran scheitern, dass IndexOf() seinerseits die Liste zumindest teilweise durchgeht und damit der Vorteil wieder futsch ist, wenn viele ausgwählt sind.
Soviel zur Theorie. Die Praxis werde ich morgen mal testen. Vermutlich müsste ich mal größere Listen generieren lassen, um es zu testen.
Danke nochmal, Alex