Dường như bạn đang làm việc với chuỗi thay vì mảng. Trong trường hợp này, bạn cần chức năng này:
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;
Hãy làm việc này.
Trước hết, tôi phân bổ biến kết quả. Đây có thể là phân bổ quá mức. Chúng tôi biết rằng kết quả không thể lớn hơn đầu vào.
Chúng tôi sử dụng hai biến địa phương lập chỉ mục, tên được đặt tên yếu hơn là i
và j
. Chúng tôi có thể cung cấp cho họ tên mô tả nhưng đối với một chức năng ngắn như vậy có thể quyết định rằng nó không cần thiết. Đừng cảm thấy tự do để đến với các tên khác nếu bạn thích. Bạn có thể chọn idxIn
và idxOut
chẳng hạn.
Một biến sẽ lập chỉ mục đầu vào, chỉ số khác sẽ lập chỉ mục đầu ra. Chỉ mục đầu vào được sử dụng trong một vòng lặp đơn giản. Chỉ số đầu ra được tăng lên mỗi lần chúng tôi tìm thấy một mục duy nhất.
Điều kiện if
kiểm tra xem chỉ mục đầu vào có liên quan đến một ký tự khác với chỉ số trước đó hay không. Phần tử đầu tiên không có phần tử trước đó vì vậy chúng tôi luôn luôn bao gồm nó.
Khi vòng lặp hoàn tất, chúng tôi biết khoảng thời gian đầu ra là bao lâu và có thể thực hiện phân bổ cuối cùng.
Điều chỉnh điều này cho một mảng rất đơn giản. Bạn chỉ cần tính toán các mảng bằng cách sử dụng các chỉ mục dựa trên zero. Đối với một chút niềm vui, đây là một phiên bản chung cho các mảng:
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;
Lưu ý vị trí một cách tinh tế khác nhau của inc(j)
. Điều này là cần thiết bởi việc chuyển sang chỉ mục dựa trên zero.
Một thay thế hơi phức tạp hơn với các bài kiểm tra ít sẽ là:
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;
tôi sẽ di chuyển '(i = 0)' so ra khỏi vòng lặp. Yếu tố đầu tiên có thể được thêm vào một cách mù quáng, chỉ những phần tử cho 'i> 0' cần được so sánh (điều này đúng với mọi * người kế thừa). Nếu chúng ta thêm đầu tiên và để cho vòng lặp bắt đầu tại chỉ mục 1, chúng ta phải thực hiện việc kiểm tra này một lần, thay vì 'High (Result)' lần. – JensG
@ JensG Cảm ơn vì điều đó. Nó hiệu quả hơn theo cách tôi đồng ý. Nhưng nó dễ đọc hơn. Đó là những gì tôi đang hướng đến cho trải nghiệm của người hỏi. Nhưng tôi đảm bảo quan điểm của bạn. –