Entwickler-Ecke

Sonstiges (Delphi) - TStringList auf mehrfach eingetragene Werte prüfen


Killi - Di 24.06.03 17:56
Titel: TStringList auf mehrfach eingetragene Werte prüfen
Hi!

Dieser Code hier tut nicht:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
procedure TForm1.Button1Click(Sender: TObject);
var
        Liste: TStringList;
        Del: TStringList;
        i, a, count: integer;
        tmp: string;
        ok: boolean;
begin

        Liste:= TStringList.Create;
        Liste.Clear;
        Del:= TStringList.Create;
        Del.Clear;

        Liste.Add('Steffen');
        Liste.Add('Hans');
        Liste.Add('Steffen');
        Liste.Add('Wurschd');
        Liste.Add('Felix');
        Liste.Add('Felix');

        for a:= 0 to Liste.Count - 1 do
        begin
                tmp:= Liste.Strings[a];
                for i:= a + 1 to Liste.Count - 1 do
                begin
                        if Liste.Strings[i] = Liste.Strings[a] then
                        begin
                                Liste.Delete(i);
                        end;
                end;
        end;

        User.Lines:= Liste;
end;

ist ja klar, da sich Liste.Count ändert....aber egal wie ich denke, es klappt nicht - kommt immer aufs gleiche raus - wie macht ihr das???

Moderiert von user profile iconTino: Code- durch Delphi-Tags ersetzt.


GruppeCN - Di 24.06.03 18:11

Wie wärs damit:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
procedure TForm1.Button1Click(Sender:TObject);
var liste:TStringList;
      s:string;
      i,j:integer;
begin
  liste := TStringList.Create;
  liste.Add('eins');
  Liste.Add('Steffen'); 
  Liste.Add('Hans'); 
  Liste.Add('Steffen'); 
  Liste.Add('Wurschd'); 
  Liste.Add('Felix'); 
  Liste.Add('Felix');

  for i:=0 to liste.count -1 do
  begin
    s := liste[i];
    for j := 0 to liste.count-1 do
    begin
      if s = liste[j] then liste.delete(j);
    end;
  end;
end;


Killi - Di 24.06.03 18:18

das ist doch haargenau das gleiche wie bei mir!
Liste out of Bounds - hat nicht mehr soviele EInträge, weil ein paar gelöscht werden - die FOR ...TO... schleife ist also nicht mehr aktuell da sie auf mehr zugreift als EInträge NOCH da sind!


Delete - Di 24.06.03 20:19

Dann lass sie runterlaufen mit downto.


Delete - Di 24.06.03 20:32

Ähem, schon mal was von IndexOf gehört? Ist eine Eigenschaft/Methode von Stringlisten.


mimi - Di 24.06.03 21:28


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
procedure TForm1.Button1Click(Sender: TObject); 
var 
        Liste: TStringList; 
        i: integer; 
        ok: boolean; 
begin 

        Liste:= TStringList.Create; 
        Liste.Clear; 

        Liste.Add('Steffen'); 
        Liste.Add('Hans'); 
        Liste.Add('Steffen'); 
        Liste.Add('Wurschd'); 
        Liste.Add('Felix'); 
        Liste.Add('Felix'); 
        for i:=0 to Liste.Count -1 do begin
          if Liste.IndexOf(Liste.Strings[i]) >-1 then
           Liste.Delete(i);
        end;

        User.Lines:= Liste; 
end;


Keldorn - Di 24.06.03 21:40

Hallo mimi

den Hinweis von Luckie hast du gelesen? mit deinem Code bekommst du auch eine Exception.
Außerdem werden alle Items gelöscht, da

Quelltext
1:
 Liste.IndexOf(Liste.Strings[i])                    

immer gefunden wird, du mußt schon prüfen, daß der gefundene Index nicht mit dem Schleifenzähler übereinstimmt.

auf die Schnelle


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
        for i:=Liste.Count -1  downto 0 do
          begin
            if Liste.IndexOf(Liste.Strings[i]) <>i then
              Liste.Delete(i);
          end;

        ListBox1.Items.Assign(Liste);

mfg Frank


mimi - Di 24.06.03 21:53

Ja den hinweise habe ich gelsesn und habe es vergessen zu beachten, passiert mir immer wieder und ich wunder mich nacher warum es nicht geht :D

dein code wird auch nicht funktioniere, indexOf gibt den gefunden index rauß wird keiner gefunden gibt er null zurück deshalb die if abfrage > 0 wenn dann lösche anderenfalls nicht.
der code sollte aber jetzt gehen(ungetestet)


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
  for i:=Liste.Count -1  downto 0 do  begin 
    if Liste.IndexOf(Liste.Strings[i]) > 0then 
      Liste.Delete(i); 
    end

        ListBox1.Items.Assign(Liste); // das ist egal wie man das macht, da gibt es verschiedne wege....


BeniSchindler - Di 24.06.03 21:56

Lagere die Überprüfung in eine Eigene Prozedur aus, die sich rekursiv aufruft. Dauert ein bischen länger aber ergibt keine Fehlermeldung.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
procedure a ;
var  
        Liste: TStringList;  
        i: integer;  
        ok: boolean;  
begin  

        Liste:= TStringList.Create;  
        Liste.Clear;  

        Liste.Add('Steffen');  
        Liste.Add('Hans');  
        Liste.Add('Steffen');  
        Liste.Add('Wurschd');  
        Liste.Add('Felix');  
        Liste.Add('Felix');  
       
       procedure TestStringList(Liste);

        User.Lines:= Liste;  
end;

procedure TestStringList(AStringList : TStringList);
var
  a,b : index;
begin 
   for a := 0 to AStringListe.Count -1 do begin
     for b := a+1 to AStringListe.Count -1 do begin
        if AStringList.strings[a] := AStringList.strings[b] then begin
           Liste.Delete(i);
           TestStringList(AStringList);
           exit;
         end
     end;
   end;
end;




andere möglichkeit ist volgendes:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
 a := -1;
 repeat  
    inc(a);
    tmp:= Liste.Strings[a]; 
    i := a;
    repeat
         inc(i);     
         if Liste.Strings[i] = Liste.Strings[a] then 
         begin 
             Liste.Delete(i);
             dec(i); 
         end
    until i =  Liste.Count-1;
 until a = Liste.Count - 2;


Keldorn - Di 24.06.03 22:01

@mimi

mfg Frank

Moderiert von user profile iconTino: List-Tag hinzugefügt.


mimi - Di 24.06.03 23:07

@Keldorn
und was ist an meiner funktion jetzt falsch ?
die sollte doch jetzt funktionieren.....


Keldorn - Mi 25.06.03 08:14

mimi hat folgendes geschrieben:
@Keldorn
und was ist an meiner funktion jetzt falsch ?
die sollte doch jetzt funktionieren.....

warum probierst Du's einfach nicht aus?

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
Liste.Add('Steffen');   
Liste.Add('Hans');   
Liste.Add('Steffen');   
Liste.Add('Wurschd');   
Liste.Add('Felix');   
Liste.Add('Felix');

du fängst mit 'Felix' hinten an

Delphi-Quelltext
1:
if Liste.IndexOf(Liste.Strings[i])                    

ergibt 4, damit fliegt der 1. Felix-eintrag raus. jetzt steht drin:
Zitat:
Steffen
Hans
Steffen
Wurschd
Felix

nächster Eintrag also gehts mit 'Felix' weiter

Delphi-Quelltext
1:
if Liste.IndexOf(Liste.Strings[i])                    

ergibt wieder 4 (=dein aktueller Schleifen zähler), damit fliegt er auch wieder aus der Liste, die Einträge, wo der Indexof und schleifenzähler gleich sind, sind nur einmal in der Liste drin und brauchen nicht gelöscht werden. Jetzt klar?

Mfg Frank


Delete - Mi 25.06.03 09:56

So geht´s auch:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
var
  Liste : TStringList;
  i     : integer;
begin
  Liste:= TStringList.Create;

  with Liste do try
    User.Clear;
    User.Lines.BeginUpdate;

    Clear;
    Add('Steffen');
    Add('Hans');
    Add('Steffen');
    Add('Keldorn');
    Add('mimi');
    Add('Wurst');
    Add('Felix');
    Add('Mathias');
    Add('Felix');
    Add('Steffen');
    Add('mimi');
    Add('Keldorn');
    Add('Luckie');

    // Variante #1 -
    // nur die neuen Strings an das Memo weiterreichen
    for i := 0 to Count - 1 do
      if(User.Lines.IndexOf(Strings[i]) = -1then
        User.Lines.Add(Strings[i]);

    // Variante #2 -
    // die Stringliste selbst "aufräumen" ...
    for i := Count - 1 downto 0 do
      if(IndexOf(Strings[i]) <> -1and (IndexOf(Strings[i]) <> i) then
        Delete(i);

    // ... und an das Memo weiterreichen
    User.Lines.Text := User.Lines.Text + #13#10 + Text;


    User.Lines.EndUpdate;
  finally
    Free;
  end;
end;


Killi - Mi 25.06.03 10:13

@BeniSchindler: Deine Codes sind nicht zu gebrauchen! Der eine gibt WIEDER genau die gleiche Meldung aus und deine Schleife greift auf globale Variablen (Liste) zu, sowas macht man nicht wenn es nicht unebdingt sein muss - und das muss es nicht!

@MathiasSimmack: thx, endlich mal etwas das klappt :-D


BeniSchindler - Mi 25.06.03 13:50

War ein Schreibfehler. Soll natürlich auf AStringList zugreifen. Und diese Variable wird ja übergeben an die Prozedure.

Und das zweite Beispiel sollte ja nicht in eine eigene Prozedur. Ist aber jetzt ja auch schon egal, da du ja jetzt eine funktionierende Prozedure hast.