Sie scheinen mit Zeichenfolgen anstelle von Arrays zu arbeiten. In diesem Fall benötigen Sie diese Funktion:
function RemoveAdjacentDuplicates(const X: string): string;
var
i, j: Integer;
begin
SetLength(Result, Length(X));
j := 0;
for i := 1 to Length(Result) do
if (i=1) or (X[i]<>X[i-1]) then
begin
inc(j);
Result[j] := X[i];
end;
SetLength(Result, j);
end;
Lassen Sie uns das durcharbeiten.
Zuallererst weise ich die Ergebnisvariable zu. Dies ist wahrscheinlich eine Überzuteilung. Wir wissen, dass das Ergebnis nicht größer als die Eingabe sein kann.
Wir verwenden zwei indexierende lokale Variablen, die eher schwach i
und j
genannt werden. Wir könnten ihnen beschreibende Namen geben, aber für solch eine kurze Funktion könnte man entscheiden, dass es nicht notwendig war. Fühlen Sie sich frei, andere Namen zu finden, wenn Sie bevorzugen. Sie könnten zum Beispiel idxIn
und idxOut
wählen.
Eine Variable indiziert den Eingang, der andere indiziert den Ausgang. Der Eingangsindex wird in einer einfachen for-Schleife verwendet. Der Ausgabe-Index wird jedes Mal erhöht, wenn wir ein eindeutiges Element finden.
Die if
Bedingung testet, ob sich der Eingangsindex auf ein Zeichen bezieht, das sich von dem vorherigen unterscheidet. Das erste Element hat kein vorheriges Element, also schließen wir es immer ein.
Sobald die Schleife abgeschlossen ist, wissen wir, wie lange die Ausgabe ist und die endgültige Zuordnung durchführen können.
Die Anpassung für ein Array ist einfach. Sie müssen nur Arrays mit nullbasierten Indizes berücksichtigen. Für ein bisschen Spaß, hier ist eine generische Version für Arrays:
type
TMyArrayHelper = class
class function RemoveAdjacentDuplicates<T>(const X: array of T): TArray<T>;
static;
end;
class function TMyArrayHelper.RemoveAdjacentDuplicates<T>
(const X: array of T): TArray<T>;
var
i, j: Integer;
Comparer: IEqualityComparer<T>;
begin
Comparer := TEqualityComparer<T>.Default;
SetLength(Result, Length(X));
j := 0;
for i := 0 to high(Result) do
if (i=0) or not Comparer.Equals(X[i], X[i-1]) then
begin
Result[j] := X[i];
inc(j);
end;
SetLength(Result, j);
end;
Notiere die auf subtile Weise anders Platzierung von inc(j)
. Dies wird durch den Wechsel zur nullbasierten Indizierung notwendig.
Eine etwas komplexere Alternative mit weniger Tests wäre:
class function TMyArrayHelper.RemoveAdjacentDuplicates<T>
(const X: array of T): TArray<T>;
var
i, j, len: Integer;
Comparer: IEqualityComparer<T>;
begin
Comparer := TEqualityComparer<T>.Default;
len := Length(X);
SetLength(Result, len);
if len=0 then
exit;
Result[0] := X[0];
j := 1;
for i := 1 to len-1 do
if not Comparer.Equals(X[i], X[i-1]) then
begin
Result[j] := X[i];
inc(j);
end;
SetLength(Result, j);
end;
Ich würde den '(i = 0)' Vergleich aus der Schleife bewegen. Das erste Element kann blind hinzugefügt werden, nur diejenigen für 'i> 0' müssen verglichen werden (was für * jeden * Nachfolger gilt). Wenn wir die erste hinzufügen und die Schleife bei Index 1 beginnen lassen, müssen wir diese Überprüfung genau einmal durchführen, anstatt "High (Result)" mal. – JensG
@JensG Danke dafür. Es ist effizienter, als ich zustimme. Aber es ist einfacher, meinen Weg zu lesen. Was ich angestrebt habe angesichts der Erfahrung des Fragestellers. Aber ich nehme deinen Standpunkt mit Sicherheit. –