Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi TListView Duplikate rückwärts löschen (https://www.delphipraxis.net/71562-tlistview-duplikate-rueckwaerts-loeschen.html)

DieHardMan 17. Jun 2006 03:14


TListView Duplikate rückwärts löschen
 
Könnte mir jemand helfen diese Prozedur zum laufen zu bekommen? Es soll von allen doppelten Einträgen immer nur das unterste Item übrigbleiben. Hab schon länger rumprobiert bekomm aber immer nen "out of bounds" Fehler, sollte wohl andersrum anfangen also bei lv.items.count - 1 und vielleicht wär ne for schleife auch besser aber irgendwie krieg ichs grad net hin.

Delphi-Quellcode:
procedure DeleteFirstDoubles(lv: TListView; SubItem: integer = -1);
var
  li1                         : TListItem;
  li2                         : TListItem;

  x                          : integer;
  y                          : integer;

begin
  if lv.Items.Count < 1 then Exit;

  x := 0;

  while x <= lv.Items.Count - 1 do
    begin
      li1 := lv.Items[x];

      y := x + 1;
      while y <= lv.Items.Count - 1 do
        begin
          li2 := lv.Items[y];

          if SubItem > -1 then
            begin
              if AnsiSameText(li1.SubItems[SubItem], li2.SubItems[SubItem]) then
                li1.Delete;
            end
          else
            begin
              if AnsiSameText(li1.Caption, li2.Caption) then
                li1.Delete;
            end;
          inc(y);
        end;

      inc(x);
    end;
end;

_frank_ 17. Jun 2006 04:04

Re: TListView Duplikate rückwärts löschen
 
ich habs mal so geändert, dass es funktioniert (ansiCompareText nur, weil AnsiSameText in D3 nicht existiert)

das ganze ist jetzt rückwärts...

Delphi-Quellcode:
procedure DeleteFirstDoubles(lv: TListView; SubItem: integer);
var
  li1,li2: TListItem;
  x,y   : integer;
begin
  if lv.Items.Count < 1 then Exit;
  x := lv.Items.Count - 1;
  while x >= 1 do
  begin
    li1 := lv.Items[x];
    y := x - 1;
    while y >= 0 do
    begin
      li2 := lv.Items[y];
      if SubItem > -1 then
      begin
        if AnsiCompareText(li1.SubItems[SubItem], li2.SubItems[SubItem])=0 then
          li2.Delete;
      end else
      begin
        if AnsiCompareText(li1.Caption, li2.Caption)=0 then
          li2.Delete;
      end;
      dec(y);
    end;
    dec(x);
  end;
end;
Gruß Frank

marabu 17. Jun 2006 10:04

Re: TListView Duplikate rückwärts löschen
 
Guten Morgen,

hier noch eine tageslichttaugliche Alternative:

Delphi-Quellcode:
procedure RemoveDuplicates(items: TListItems; index: Integer);
var
  i: Integer;
  isEqual: Boolean;
begin
  items.BeginUpdate;
  for i := Pred(items.Count) downto 1 do
  begin
    if index < 0
      then isEqual := AnsiSameText(items[Pred(i)].Caption, items[i].Caption)
      else isEqual := AnsiSameText(items[Pred(i)].Subitems[index], items[i].Subitems[index]);
    if isEqual then
      items[Pred(i)].Delete;
  end;
  items.EndUpdate;
end;
Grüße vom marabu

DieHardMan 17. Jun 2006 13:08

Re: TListView Duplikate rückwärts löschen
 
@marabu, dein Code funktioniert zwar, vergleicht aber nur die aufeinanderfolgenden Items auf Gleichheit und nicht alle, dazu sind 2 Schleifen nötig.

@frank, funktioniert solange bis die Prozedur versucht auf Items zuzugreifen die es soeben gelöscht hat, dann kommt ne EAccessViolation. Man müsste da noch prüfen ob das Item existiert und den Durchlauf überspringen.

Hawkeye219 17. Jun 2006 13:53

Re: TListView Duplikate rückwärts löschen
 
Hier ist noch eine Variante:

Delphi-Quellcode:
procedure RemoveDuplicates (Items: TListItems; Index: Integer = -1);
  var i : Integer;
      s : string;
      L : TStrings;
begin
  L := TStringList.Create;
  for i := Items.Count - 1 downto 0 do
    begin
      if (Index < 0) then
        s := Items[i].Caption
      else
        s := Items[i].SubItems[Index];
      if (L.IndexOf(s) < 0) then
        L.Add(s)
      else
        Items[i].Delete;
    end;
  L.Free;
end;
Gruß Hawkeye

_frank_ 17. Jun 2006 14:25

Re: TListView Duplikate rückwärts löschen
 
Zitat:

Zitat von DieHardMan
@frank, funktioniert solange bis die Prozedur versucht auf Items zuzugreifen die es soeben gelöscht hat, dann kommt ne EAccessViolation. Man müsste da noch prüfen ob das Item existiert und den Durchlauf überspringen.

also den Fall hatte ich nicht gehabt, bei welcher konstellatio tritt der auf? Weil ich lösche item li2 (y) und das ist beim nächsten durchlauf schon eins weiter oben...somit sollte kein AV kommen

Gruß Frank

marabu 17. Jun 2006 14:38

Re: TListView Duplikate rückwärts löschen
 
Zitat:

Zitat von DieHardMan
@marabu, dein Code funktioniert zwar, vergleicht aber nur die aufeinanderfolgenden Items auf Gleichheit und nicht alle, dazu sind 2 Schleifen nötig.

Das ist richtig. Ich ging von einer sortierten Liste aus - vielleicht weil du deine Anforderung nicht in den Text geschrieben hattest. Bei unsortierten Items sollte man eine getrennte Liste führen, die dann aber sortiert sein sollte. Du kommst dann am Ende automatisch auf den Ansatz, den Hawkeye gezeigt hat - nur fehlt dort noch die Einstellung Sorted für die TStringList.

marabu


Alle Zeitangaben in WEZ +1. Es ist jetzt 16: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 by Thomas Breitkreuz