Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Array und duplikate (https://www.delphipraxis.net/87763-array-und-duplikate.html)

delphinia 5. Mär 2007 20:23


Array und duplikate
 
Hallo

wie finde ich und was ist der effektivste Weg Duplicate in einem Array zu finden und in ein anderes Array zu schieben?

Edit: ich möchte NICHT das doppelte Array ausortieren sondern BEIDE doppelten oder mehrfachvorhandene nur verschieben

mkinzler 5. Mär 2007 20:25

Re: Array und duplikate
 
Vor dem Einfügen mit .IndexOf überprüfen.

Dani 6. Mär 2007 02:35

Re: Array und duplikate
 
Liste der Anhänge anzeigen (Anzahl: 1)
Wenn ich dich richtig interpretiere, meinst du mit effektiv eigentlich effizient, also müssen wir die Zeit und Speicherkosten berücksichtigen. Wie sieht dein Array denn aus? Was mir jetzt auf die Schnelle einfällt wäre:

1. Die Reihenfolge der Elemente in der Liste darf nicht verändert werden.
-> 1.a Alle Elemente paarweise miteinander vergleichen und Duplikate markieren (Zwei verschachtelte for-Schleifen). Aufwand für das Finden der Duplikate = O(1) bzw. O(n) Speicherverbrauch, O(n²) Zeitaufwand.
-> 1.b Alle Elemente in eine zweite Liste kopieren und diese Liste wie in 2. verarbeiten: Aufwand für das Finden der Duplikate = O(n) Speicherverbrauch, O(n * log(n)) Zeitaufwand.

2. Die Reihenfolge der Elemente in der Liste darf verändert werden.
-> 2.a Die Liste sortieren (z.B. mit Heapsort oder Quicksort), danach stehen alle Duplikate hintereinander. Aufwand für das Finden der Duplikate = O(1) Speicherverbrauch, O(n * log(n)) Zeitaufwand.

3. Die Liste ist bereits zu jedem Zeitpunkt sortiert.
-> 3.a Alle Duplikate stehen bereits hintereinander.

4. ???

Nachdem jetzt alle Duplikate entweder markiert sind oder direkt hintereinander stehen, kannst du das Array von vorne nach hinten durchlaufen und die Elemente, die doppelt oder mehrfach vorkommen, in eine andere Liste verschieben. (Frage: verschieben von A nach B = Element aus Liste A löschen und in Liste B einfügen?)

Jetzt bleibt nur noch das Problem, dass man aus einer Arraybasierten Liste nicht effizient löschen/verschieben kann, da jede Löschaktion O(n) Zeit in Anspruch nimmt. :(

Ich häng mal noch diesen völlig ungetesteten Code an, vielleicht hilft der irgendwie (und wenns nur als Beispiel dient, wie man's nicht machen sollte ^^)

Gruß Dani

delphinia 6. Mär 2007 04:24

Re: Array und duplikate
 
Hier mehr Infos:


Mein Array

Delphi-Quellcode:
type
  TDi= packed record
    S1: string;
    p1: integer;
  end;

  tdia= array of TDi;

in diesem können Strings auch mehrmals vorkommen.

DaHui 6. Mär 2007 15:07

Re: Array und duplikate
 
ganz einfach könntest du ausschliessen ob überhaupt Doppelte sachen drin vorkommen indem du (falls bekannt) die Anzahl der Stellen (oder wie das heisst in dem Array) des Arrays die der Array hat und die er haben sollte (maximal ohne Duplikate) vbergleichst und dem Programm dann in ner If Else Funktion sagst das wenn gleich gross ist ist alles ok (vorraus dein reinschreiben in den Array war lückenfrei) und dann weiter machst wie oben schon beschrieben mit Sortieren und dann stehen die ja eh hintereinandern und musst die nur noch durchgehen.

wäre meine spontane idee :)

Dani 6. Mär 2007 17:29

Re: Array und duplikate
 
Du hast es oft leichter, wenn du auf Relikte wie dynamische Arrays und Records verzichtest.

Delphi-Quellcode:
program Project2;

{$APPTYPE CONSOLE}

uses SysUtils, Classes;

type
  TDi = class(TObject)
  private
    FP1: Integer;
    FS1: String;
  public
    constructor Create(S1: String; P1: Integer);
    property S1: String read FS1 write FS1;
    property P1: Integer read FP1 write FP1;
  end;

  TDiArray = class(TList)
  public
    procedure Print;
    function ExtractDuplicates: TDiArray;
  end;

procedure TDiArray.Print;
var I: Integer;
    Item: TDi;
begin
  for I := 0 to Count - 1 do begin
    if (Items[I] <> nil) then begin
      Item := TDi(Items[I]);
      WriteLn(Item.S1  + ' = ' + IntToStr(Item.P1));
    end;
  end;
end;

(************************************
 * Annahme: DiArray ist unsortiert. *
 * Entspricht im Wesentlichen einem *
 * Bubblesort.                     *
 ************************************)
function TDiArray.ExtractDuplicates: TDiArray;
var I,J: Integer;
begin
  Result := TDiArray.Create;
  for I := 0 to Count - 1 do begin
    if (Items[I] <> nil) then
      for J := I + 1 to Count - 1 do begin
        if (Items[J] <> nil) and
           (TDi(Items[I]).S1 = TDi(Items[J]).S1) then begin
          Result.Add(Items[J]);
          Items[J] := nil;
        end;
      end;
  end;
  //Pack() aufrufen, wenn die "nil"-Löcher entfernt werden sollen.
end;

{ TDi }

constructor TDi.Create(S1: String; P1: Integer);
begin
  inherited Create;
  Self.S1 := S1;
  Self.P1 := P1;
end;

procedure Foo;
var
  Arr, Duplicates: TDiArray;
begin
  Arr := TDiArray.Create;
  Arr.Add(TDi.Create('a', 1));
  Arr.Add(TDi.Create('b', 2));
  Arr.Add(TDi.Create('b', 3));
  Arr.Add(TDi.Create('a', 4));
  Arr.Add(TDi.Create('c', 5));
  Arr.Add(TDi.Create('a', 6));
  Arr.Add(TDi.Create('b', 7));
  Arr.Add(TDi.Create('c', 8));
  Arr.Add(TDi.Create('c', 9));
  Arr.Add(TDi.Create('a', 10));
  Duplicates := Arr.ExtractDuplicates;

  WriteLn('Arr:');
  Arr.Print;
  WriteLn('Duplikate:');
  Duplicates.Print;
  ReadLn;
end;


begin
  Foo;
end.


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