Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Listbox Einträge vergl., bei Doppelbelegung einen Löschen (https://www.delphipraxis.net/122096-listbox-eintraege-vergl-bei-doppelbelegung-einen-loeschen.html)

Ginko 9. Okt 2008 11:45


Listbox Einträge vergl., bei Doppelbelegung einen Löschen
 
Hallo, ich habe folgendes Problem, also ich will die einträge einer Listbox an bestimmten stellen
vergleichen und bei Doppelbelegung einen rauslöschen. Ich habe es mit einer 'repeat' Schleife wie folgt versucht:
Delphi-Quellcode:
 
if listbox0.Items.Count = 5 then
  begin
    o:=0;
    p:=0;
    repeat
      o := o + 1;
      p := p + 1;
      if (listbox0.Items[o][5] +  listbox0.Items[o][7] + listbox0.Items[o][9]) =
         (listbox0.Items[p][5] +  listbox0.Items[p][7] + listbox0.Items[p][9]) then
           listbox0.Items.Delete(o);
    until (listbox0.Items.Count <> 5) or (o = 5);

  end;
Allerdings löscht er nicht den doppelten Eintrag sondern einfach den ersten in der Listbox, dass ist das Problem....
Wäre toll wenn jemand eine Idee hätte !

Also die Einträge sind nur an den bestimmten Stellen gleich.
also es sieht zB ein gleicher Eintrag so aus:
1) 0 1 1
4) 0 1 1

Medium 9. Okt 2008 12:05

Re: Listbox Einträge vergl., bei Doppelbelegung einen Lösche
 
o und p sind immer gleich, und dadurch ergibt dein Vergleich auch immer "true". Du müsstest wenn mit einer Doppelschleife anrücken.

Wäre es jedoch nicht prinzipiell einfacher, vor dem Einfügen eines neuen Eintrages zu prüfen ob er schon vorhanden ist, und ggf. diesen zu verwerfen?

nahpets 9. Okt 2008 12:09

Re: Listbox Einträge vergl., bei Doppelbelegung einen Lösche
 
Hallo,
p und o sind bei Dir doch immer gleich, Du vergleichst da anscheinend einen Eintrag immer mit sich selbst und da die Schleife aufhört, wenn count <> 5, wird bei 5 Einträgen nur der erste gelöscht, da danach ja nur noch 4 vorhanden sind, änderst Du
Delphi-Quellcode:
until (listbox0.Items.Count <> 5) or (o = 5);
auf
Delphi-Quellcode:
until (listbox0.Items.Count <> 3) or (o = 3);
werden entsprechend mehr Einträge gelöscht. Willst Du zwei hintereinanderliegende Einträge miteinander vergleichen, so sollte p um eins größer als o sein.
Versuchs mal damit:
Delphi-Quellcode:
if listbox0.Items.Count = 5 then
begin
  o:=1;
  repeat
    if (listbox0.Items[o][5] +  listbox0.Items[o][7] + listbox0.Items[o][9]) =
       (listbox0.Items[o - 1][5] +  listbox0.Items[o - 1][7] + listbox0.Items[o - 1][9]) then
         listbox0.Items.Delete(o);
    Inc(o);
  until (listbox0.Items.Count <> 5) or (o = 5);
end;
p ist dann überflüssig.

Ginko 9. Okt 2008 13:44

Re: Listbox Einträge vergl., bei Doppelbelegung einen Lösche
 
Hallo danke für die schnellen Antworten, also es klappt mit deiner Lösung fast, allerdings nur wenn ich 'o'
auf 4 ändere
Delphi-Quellcode:
  if listbox0.Items.Count = 5 then
    begin
      o:=1;
      repeat
        if (listbox0.Items[o][5] +  listbox0.Items[o][7] + listbox0.Items[o][9]) =
           (listbox0.Items[o - 1][5] + listbox0.Items[o - 1][7] + listbox0.Items[o - 1][9]) then
            listbox0.Items.Delete(o);
            Inc(o);
      until (listbox0.Items.Count <> 5) or (o = 4);
    end;
ansonsten bringt er mir nen Exception, das liegt aber denk ich mal daran, dass bei der Listbox der 'Index' bei 0
anfängt und der 'Count' normal bei 1.
Also 'o' ist ja die Indexnummer und bei 4 müsste der 'Count' auf 5 stehen, damit kein Fehler kommt, wenn ich mich nicht täusche.
Jedenfalls das Problem ist, dass der erste, der zweite und der letzte Wert nicht verglichen werden also nur wenn
wenn Idex[2] und Index[3] gleich sind wird eins gelöscht...

nahpets 9. Okt 2008 13:53

Re: Listbox Einträge vergl., bei Doppelbelegung einen Lösche
 
Hallo,

nein, Deine Annahme stimmt nicht.
Mit jedem Löschen eines Eintrages ändert sich automatisch count, so dass die Abfrage auf o = 4 nur dann stimmt, wenn Du vorher 5 Einträge hast und davon einen löschst. Das von Dir gewählte Konstrukt ist so hochgefährlich, wenn es funktioniert, dann nur unter ganz bestimmten Bedingungen, jede noch so kleine Abweichung führt zu einem Programmfehler.
Hinterfrag bitte mal, ob die Abfrage or o = 4 oder wie auch immer überhaupt erforderlich ist. Und auch die Abfrage auf count <> 5 ist gefährlich. Dass erste Löschen eines Eintrages führt ja schon dazu, dass Count <> 5 ist. In dem Falle dürfte die Abfrage auf o überflüssig sein. Eventuell wäre da ein Count <= o die sinnvollere Alternative.

DeddyH 9. Okt 2008 14:02

Re: Listbox Einträge vergl., bei Doppelbelegung einen Lösche
 
Mal so eine Idee:
Delphi-Quellcode:
procedure DeleteDoubleItems(const sl: TStrings; MaxIndex: integer = -1);
var i: integer;
begin
  sl.BeginUpdate;
  try
    if (MaxIndex < 0) or (MaxIndex >= sl.Count) then
      MaxIndex := Pred(sl.Count);
    for i := MaxIndex downto 1 do
      if sl.IndexOf(sl[i]) < i then
        sl.Delete(i);
  finally
    sl.EndUpdate;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  DeleteDoubleItems(ListBox1.Items);
end;

Ginko 9. Okt 2008 14:17

Re: Listbox Einträge vergl., bei Doppelbelegung einen Lösche
 
also
Delphi-Quellcode:
until listbox0.Items.Count <= o;
klappt auch aber er frägt nur die Werte zwischen dem ersten und letzten Index ab.
Die Äußeren werden nicht beachtet.

Ginko 9. Okt 2008 14:20

Re: Listbox Einträge vergl., bei Doppelbelegung einen Lösche
 
Hui DeddyH da blick ich jetzt als Anfänger noch gar nicht durch aber ich werd mich mal veruchen mit
zu beschäftigen, Danke dir trotzdem.

nahpets 9. Okt 2008 14:25

Re: Listbox Einträge vergl., bei Doppelbelegung einen Lösche
 
Hallo,

das wird mir zu kompliziert:
Delphi-Quellcode:
if listbox0.Items.Count = 5 then begin
  for o := listbox0.Items.Count - 1 DownTo 1 do begin
    if (listbox0.Items[o][5] +  listbox0.Items[o][7] + listbox0.Items[o][9]) =
       (listbox0.Items[o - 1][5] +  listbox0.Items[o - 1][7] + listbox0.Items[o - 1][9]) then
         listbox0.Items.Delete(o);
  end;
end;
Damit solltest Du doppelte Einträge wegbekommen. Mir ist bisher nicht klar geworden, wofür die Abfrage auf 5 oder sonstwieviele Einträge gut sein soll, sollen mindestens 5 Einträge in der Listbox überbleiben, auch wenn sie doppelt sind? Warum werden Doppelte nur entfernt, wenn mehr als 5 Einträge vorhanden sind?

Ginko 9. Okt 2008 14:37

Re: Listbox Einträge vergl., bei Doppelbelegung einen Lösche
 
Also wenn ein Eintrag gelöscht worden ist, soll die Suche beendet werden, deshalb habe ich die Beschränkung auf 5 gemacht, ansonsten sucht er ja weiter wenn er einen gelöscht hat und es sind nur noch 4 Werte da und es wird ein Fehler verursacht, weil auch an der 5ten stelle wieder gesucht wird, die aber jetzt leer ist.

Aber wie ich sehe klappt es auch mit deiner 'for' Schleife nur werden hier auch nicht alle Werte abgefagt.

nahpets 9. Okt 2008 14:43

Re: Listbox Einträge vergl., bei Doppelbelegung einen Lösche
 
Zitat:

Zitat von Ginko
Aber wie ich sehe klappt es auch mit deiner 'for' Schleife nur werden hier auch nicht alle Werte abgefagt.

Welche Werte werden nicht abgefragt? Die Forschleife sorgt dafür, dass zuerst der letzte und der vorletzte Eintrag verglichen werden, dann der vorletzte mit dem vorvorletzten ... bis der erste und der nullte Eintrag miteinander verglichen werden. Hier sollte eigentlich nichts "übersprungen" werden.

DeddyH 9. Okt 2008 14:47

Re: Listbox Einträge vergl., bei Doppelbelegung einen Lösche
 
Ohne mich selbst loben zu wollen finde ich meine Methode am Einfachsten ;)

Ginko 9. Okt 2008 14:52

Re: Listbox Einträge vergl., bei Doppelbelegung einen Lösche
 
Ja das klappt aber es sollen auch der letzte mit dem ersten, der letzte mit dem zweiten usw verglichen
werden.

Also wenn jetzt zum Beispiel an Stelle 1 (0 0 0) steht und an Stelle 5 (0 0 0) dann soll die erste stelle gelöscht werden oder wenn nicht anders möglich die 5te.

taaktaak 9. Okt 2008 14:53

Re: Listbox Einträge vergl., bei Doppelbelegung einen Lösche
 
Zitat:

ich will die einträge einer Listbox an bestimmten stellen
vergleichen und bei Doppelbelegung einen rauslöschen
Diese Aufgabenstellung erscheint mir seltsam. Warum "an bestimmten Stellen"? Oder sollen ALLE Doubletten gelöscht werden?

Grundsätzlich wäre es auch (vielleicht) sinnvoller, die Doubletten gar nicht erst in die Listbox aufzunehmen. Also z.B. mit
Delphi-Quellcode:
with ListBox1.Items do
  if IndexOf(~~)<0 then Add(~~
zu gewährleisten dass keine doppelten Einträge hinein kommen.

DeddyH 9. Okt 2008 14:55

Re: Listbox Einträge vergl., bei Doppelbelegung einen Lösche
 
Das geht aber einfacher mit Sorted auf true und Duplicates auf dupIgnore.

[edit] Kommando zurück, das gilt nur für TStringlist. [/edit]

nahpets 9. Okt 2008 14:56

Re: Listbox Einträge vergl., bei Doppelbelegung einen Lösche
 
Hallo,
Zitat:

Zitat von DeddyH
Ohne mich selbst loben zu wollen finde ich meine Methode am Einfachsten ;)

okay, Du bekommst jetzt ein gaaaaaaanz dickes Lob :thumb: :thumb: :thumb: :thumb: :thumb:
Deine Methode berücksichtig bisher noch nicht, dass beim Vergleich nur das 5. ,7. und 9. Zeichen der Einträge berücksichtigt werden sollen. :(

nahpets 9. Okt 2008 14:59

Re: Listbox Einträge vergl., bei Doppelbelegung einen Lösche
 
Hallo,
Zitat:

Zitat von Ginko
Ja das klappt aber es sollen auch der letzte mit dem ersten, der letzte mit dem zweiten usw verglichen
werden.

Also wenn jetzt zum Beispiel an Stelle 1 (0 0 0) steht und an Stelle 5 (0 0 0) dann soll die erste stelle gelöscht werden oder wenn nicht anders möglich die 5te.

Also langsam scheint bei mir der Groschen zu fallen:

Du möchtest jeden Eintrag mit jedem Eintrag vergleichen und alle die löschen, bei denen die 5., 7. und 9. Stelle übereinstimmen. Hab' ich's jetzt verstanden :?:

DeddyH 9. Okt 2008 15:01

Re: Listbox Einträge vergl., bei Doppelbelegung einen Lösche
 
Unter "doppeltem Eintrag" verstehe ich aber etwas anderes :?

Ginko 9. Okt 2008 15:07

Re: Listbox Einträge vergl., bei Doppelbelegung einen Lösche
 
Ja genau also die Einträge sind nur an den bestimmten Stellen gleich.
also es sieht zB ein gleicher Eintrag so aus:
1) 0 1 1
4) 0 1 1
aber sollte es zu kompliziert sein werde ich es vielleicht erstmal versuchen es vor dem Eintrag abzufangen, wobei das sicher auch nicht viel einfacher geht.

bernau 9. Okt 2008 15:11

Re: Listbox Einträge vergl., bei Doppelbelegung einen Lösche
 
Zitat:

Zitat von DeddyH
Das geht aber einfacher mit Sorted auf true und Duplicates auf dupIgnore.

[edit] Kommando zurück, das gilt nur für TStringlist. [/edit]

Dann sollte doch folgendes gehen

Delphi-Quellcode:
var
  sl:TStriglist;
begin
  sl:=TStriglist.create;
  sl.duplicates:=dupIgnore;
  sl.assign(sllistbox0.Items);
  sllistbox0.Items.assign(sl);
  sl.free;
end;

Edit: Bei mir auch komando zurück. Habe den ersten Post zu schnell überflogen. ;-)

Ginko 9. Okt 2008 15:16

Re: Listbox Einträge vergl., bei Doppelbelegung einen Lösche
 
bernau das berücksichtigt aber nicht das die ersten beiden Stellen unterschiedlich sein können oder ?
Ah sehe 'edit' auch zurück

bernau 9. Okt 2008 15:29

Re: Listbox Einträge vergl., bei Doppelbelegung einen Lösche
 
OK. Anderer Versuch. Ich würde mit einer Hilfsstrinliste arbeiten

Delphi-Quellcode:

var
 sl:TStringlist;
 stri:String;
begin
  sl:=TStringlist.create;

  // downto verwenden, da items zwischendurch gelöscht werden können
  for a:=sllistbox0.Items.count-1 downto 0 do
    begin
      stri:=listbox0.Items[a][5] +  listbox0.Items[a][7] + listbox0.Items[a][9];

      if sl.indexof(stri)>=0 then
        listbox0.items.delete(a)
      else
        sl.add(stri);

    end;

  sl.free;
end;

Einfach so runtergetippt und nicht getestet

nahpets 9. Okt 2008 15:47

Re: Listbox Einträge vergl., bei Doppelbelegung einen Lösche
 
Hallo,

so, letzter Versuch :P
Delphi-Quellcode:
for i := listbox0.items.count - 1 DownTo 0 Do begin
  for k := i - 1 DownTo 0 Do begin
    if (i < listbox0.items.count - 1)
    and (k < listbox0.items.count - 1) then begin
      if listbox0.items[i][5] + listbox0.items[i][7] + listbox0.items[i][9]
       = listbox0.items[k][5] + listbox0.items[k][7] + listbox0.items[k][9] then begin
        listbox0.items.Delete(k);
      end;
    end;
  end;
end;

Ginko 9. Okt 2008 18:05

Re: Listbox Einträge vergl., bei Doppelbelegung einen Lösche
 
Nach einer kleinen Änderung klappt es nun danke dir nahpets!:thumb:

Delphi-Quellcode:
for i := listbox0.items.count DownTo 0 Do begin
  for k := i - 1 DownTo 0 Do begin
    if (i < listbox0.items.count)
    and (k < listbox0.items.count) then begin
      if listbox0.items[i][5] + listbox0.items[i][7] + listbox0.items[i][9]
       = listbox0.items[k][5] + listbox0.items[k][7] + listbox0.items[k][9] then begin
        listbox0.items.Delete(k);
      end;
    end;
vorher wurde der letzte Eintrag nicht berücksichtigt.
bernau deine Methode hab ich jetzt noch nicht getestet aber, trotzdem danke.


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:15 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz