schon seit einiger Zeit knoble ich an dem Vorhaben 2 Listen zu vergleichen in denen Namen stehen. Und ich möchte diese Listen gegeneinander abgleichen und eine dritte Liste erstellen mit Namen die in Liste 2 aber nicht in Liste 1 enthalten sind.
Da ich ziemlich der Neuling bin im programmieren finde ich keinen Ansatz und ich weiß auch nicht so Recht wo ich Beispiele finden könnte.
saxoBeat hat geschrieben:Und ich möchte diese Listen gegeneinander abgleichen und eine dritte Liste erstellen mit Namen die in Liste 2 aber nicht in Liste 1 enthalten sind.
Alle Namen aus Liste 1 sind immer in Liste 2? Ist jeder Name maximal 1 Mal in jeder Liste enthalten?
Dann gibt es prinzipiell zwei Ansätze:
Sortiere Listen vergleichen
Beide Arrays werden sortiert. In einer Schleife geht man die Quellliste durch und schaut ob es den Eintrag ebenfalls in der Suchliste gibt. Die Array-Indizes richtig zu verwenden ist nicht ganz so einfach (dafür hat man nach der Übung nie wieder Probleme damit).
Namen aus Liste 2 in Liste 1 suchen
Hier ist es an sich egal, ob die Listen sortiert sind oder ob Namen doppelt enthalten sind. Man geht in einer Schleife die Quellliste durch und sucht mittels Suchfunktion in der Suchliste. Wenn die Suchliste sortiert ist (Normalfall: Unsortiert = lineare Suche), kann man effizientere Suchalgorithmen wie die binäre Suche oder die Interpolationssuche.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Nicht schnell und besonder komfortabel, doch zum verstehen am besten, wäre es sinnvoll die zwei "Array of String"s mittels zweier Schleifen zu vergleichen.
procedure TForm1.Button1Click(Sender: TObject);
var
s1,s2,s3:array of string;
x,y:integer;
found:boolean;
begin
setlength(s1,random(20)); //Länge von S1 per Zufall definieren
setlength(s2,random(20));
setlength(s3,0); //Länge von S3 ist null, da hier dann die in S1 und S2 nicht vorhandenen Strings hineinkommen
for x:=0 to high(s1) do s1[x]:='String '+inttostr(x); //Füllen der "Array of String"s mit irgendwelchen Inhalten
for x:=0 to high(s2) do s2[x]:='String '+inttostr(x*2); //Füllen der "Array of String"s mit irgendwelchen Inhalten
for x:=0 to high(s1) do begin //Als erstes schauen, welche Strings von S1 nicht in S2 vorhanden sind
found:=false;
y:=0;
while (y<=high(s2)) and not found do
if s1[x]=s2[y] then found:=true
else inc(y);
if not found then begin //Wurde der String von S1 nicht in S2 gefunden, diesen dann in S3 einfügen
setlength(s3,length(s3)+1);
s3[high(s3)]:=s1[x];
end;
end;
for x:=0 to high(s2) do begin //Als zweites schauen, welche Strings von S2 nicht in S1 vorhanden sind
found:=false;
y:=0;
while (y<=high(s1)) and not found do
if s2[x]=s1[y] then found:=true
else inc(y);
if not found then begin //Wurde der String von S2 nicht in S1 gefunden, diesen dann in S3 einfügen
setlength(s3,length(s3)+1);
s3[high(s3)]:=s2[x];
end;
end;
memo1.Clear;
for x:=0 to high(s3) do memo1.Lines.Add(s3[x]);
end;
Function CmpLst(Lst1, lst2: TStringList): TStringList;
Var lstT: TStringList;
i: Integer;
Begin
lstT := TStringList.Create;
lstT.AddStrings(Lst1);
Result := TStringList.Create;
Result.AddStrings(lst2);
While (lstT.Count > 0) Do
Begin
i := Result.IndexOf(lstT[0]);
If i >= 0 Then Result.delete(i);
lstT.Delete(0);
End;
sltT.Free;
End;
Ein Array of Strings würde ich niemals für so was nehmen.
Nimm nicht "Arrays" von Strings, sondern TStringLists. Dann kannst Du die mit "Bordmitteln" (TStringList.Sorted := TRUE; ) sortieren und damit ist der Vergleich einfach: In einer Schleife den Index von dem der Liste, wo der Index gerade auf auf das kleinere Element zeigt inkrementieren. Dann hast Du bei Wechsel der "aktuell größeren" Liste immer die Indizes der nahe zusammenliegenden Elemente und kannst damit Deine Entscheidungen treffen.
Nimm nicht "Arrays" von Strings, sondern TStringLists.
+1 !!!
Das war aber nicht die Frage. Zum verstehen und lernen finde ich den Ansatz die Listen per Hand zu sortieren erstmal besser! Effizienz kommt dann später.