Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Delete duplicates from list (https://www.delphipraxis.net/165516-delete-duplicates-list.html)

WojTec 3. Jan 2012 18:32

Delphi-Version: 2010

Delete duplicates from list
 
Delphi-Quellcode:
var
  S: string;
  I: Integer;
begin
  for S in List do
  begin
    I := List.IndexOf(S);
    while I = -1 do
    begin
      List.Delete(I);
      I := List.IndexOf(S);
    end;
  end;
end;
...but nothing happen after this. List is TStrings. F1 :(

Klaus01 3. Jan 2012 18:41

AW: Delete duplicates from list
 
.. could it be that I has never value -1
because S is in the List and you will get for I the position in the List of S.

Delphi-Quellcode:
for S in List do
  begin
    I := List.IndexOf(S);
    while I = -1 do
    begin
      List.Delete(I);
      I := List.IndexOf(S);
    end;
  end;
edit:
If you want to use TStringList there is an property called duplicates
This can be set to avoid duplicate entries in the list.

Best regards
Klaus

DeddyH 3. Jan 2012 18:48

AW: Delete duplicates from list
 
Delphi-Quellcode:
var
  S: string;
  I, J: Integer;
begin
  for S in List do
  begin
    I := List.IndexOf(S);
    for J := List.Count - 1 downto I + 1 do
      if List[J] = S then
        List.Delete(J);
  end;
end;
Or use a TStringlist as Klaus said before (this TStringlist must have set Sorted to true).

WojTec 3. Jan 2012 19:07

Re: Delete duplicates from list
 
I found example for TStringList:
Code:
http://delphi.about.com/od/delphitips2009/qt/remove-duplicat.htm
but, first is for TStringList - I need for TStrings - it's component property, and second uses sorting and data order is important, so I can't sort it. Thanks for help, guys :D

Klaus01 3. Jan 2012 19:11

AW: Delete duplicates from list
 
Delphi-Quellcode:
sList := TStringList.create;
try
  sList.sorted := true;
  sList.duplicates := dupIgnore;
  sList.assign(List);



  List.assign(sList);
finally
  sList.free;
end;
not tested.

Best regards
Klaus

Bjoerk 3. Jan 2012 21:03

AW: Delete duplicates from list
 
Alternative:

Delphi-Quellcode:
procedure RemoveDoubles(Strings: TStrings);
var
  I, J: integer;
begin
  Strings.BeginUpdate;
  I:= 0;
  while I <= Strings.Count-2 do
  begin
    J:= I+1;
    while J <= Strings.Count-1 do
    begin
      if Strings[I] = Strings[J] then
      begin
        Strings.Delete(J);
        Dec(J);
      end;
      Inc(J);
    end;
    Inc(I);
  end;
  Strings.EndUpdate;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  RemoveDoubles(Memo1.Lines);
end;

DeddyH 4. Jan 2012 07:02

AW: Delete duplicates from list
 
Da finde ich meinen Vorschlag aber übersichtlicher (nix für ungut).

Furtbichler 4. Jan 2012 07:40

AW: Delete duplicates from list
 
Schneller (ohne Sort):
Delphi-Quellcode:
For i := List.Count - 1 downto 0 do
  For j := List.Count - 1 downto i + 1 do
    If s[i]=s[j] then
      s.delete(j);
@DeddyH:
Delphi-Quellcode:
 for S in List do I := List.IndexOf(S);
entspricht doch
Delphi-Quellcode:
For i := 0 to List.Count-1 do S := List[i];
, nur das Letzteres um eine Größenordnung performanter ist oder irre ich mich?

DeddyH 4. Jan 2012 07:46

AW: Delete duplicates from list
 
Das mag schon sein, ein wenig C&P sei mir doch gegönnt.

Furtbichler 4. Jan 2012 07:47

AW: Delete duplicates from list
 
Ohne Quellenangabe? :mrgreen:

DeddyH 4. Jan 2012 07:59

AW: Delete duplicates from list
 
^^ Ich habe das jetzt nochmal ins Reine geschrieben und versucht, dabei möglichst simpel zu bleiben.
Delphi-Quellcode:
procedure DeleteDuplicates(const List: TStrings);
var
  CurrentIndex, FollowingIndex: integer;
begin
  Assert(Assigned(List));
  List.BeginUpdate;
  try
    CurrentIndex := 0;
    while CurrentIndex < List.Count - 1 do
      begin
        for FollowingIndex := List.Count - 1 downto CurrentIndex + 1 do
          if List[CurrentIndex] = List[FollowingIndex] then
            List.Delete(FollowingIndex);
        Inc(CurrentIndex);
      end;
  finally
    List.EndUpdate;
  end;
end;

procedure DeleteDuplicatesCaseInsensitive(const List: TStrings);
var
  CurrentIndex, FollowingIndex: integer;
begin
  Assert(Assigned(List));
  List.BeginUpdate;
  try
    CurrentIndex := 0;
    while CurrentIndex < List.Count - 1 do
      begin
        for FollowingIndex := List.Count - 1 downto CurrentIndex + 1 do
          if AnsiLowerCase(List[CurrentIndex]) = AnsiLowerCase(List[FollowingIndex]) then
            List.Delete(FollowingIndex);
        Inc(CurrentIndex);
      end;
  finally
    List.EndUpdate;
  end;
end;
Wer mag, kann auch auf StrUtils u.a. zurückgreifen, so sollte es aber schon funktionieren.

sx2008 4. Jan 2012 08:32

AW: Delete duplicates from list
 
Die äussere For-Schleife hat aber mehr Durchläufe als nötig.
Ich würde da eine While-Schleife verwenden, die dann abbricht wenn es nichts mehr zu tun gibt.
Ungetestet:
Delphi-Quellcode:
CurrentIndex := 0
while CurrentIndex < List.Count - 1 do
begin
  for FollowingIndex := List.Count - 1 downto CurrentIndex + 1 do
    if List[CurrentIndex] = List[FollowingIndex] then
      List.Delete(FollowingIndex);
  Inc(CurrentIndex);
end;
Hätte die Stringliste z.B. 1000 identische Einträge würde die While-Schleife schon nach einem Durchlauf abbrechen, während eine For-Schleife alle restlichen 999 Einträge erfolglos durchtesten würde.

DeddyH 4. Jan 2012 08:35

AW: Delete duplicates from list
 
Stimmt, ich hatte vergessen, dass for die Anzahl nur einmalig ermittelt.

[edit] Korrigiert [/edit]

Iwo Asnet 4. Jan 2012 08:56

AW: Delete duplicates from list
 
Das selbst in soetwas scheinbar banalem der Teufel (nun ja, ein Teufelchen) im Detail stecken kann...


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:35 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