Fabio Vitale
Fabio Vitale

Reputation: 2287

How to remove repeated spaces from a string

I need to remove repeated spaces from a string. The following code, grabbed from internet, works decently except that it duplicate the first char of the string. Also maybe there is something faster that this.

function DeleteRepeatedSpaces(OldText: string): string;
var
  i: integer;
  s: string;
begin
   if length(OldText) > 0 then
    s := OldText[1]
  else
    s := '';

  for i := 1 to length(OldText) do
  begin
    if OldText[i] = ' ' then
    begin
      if not (OldText[i - 1] = ' ') then
        s := s + ' ';
    end
    else
    begin
      s := s + OldText[i];
    end;
  end;

  DelDoubleSpaces := s;
end;

Upvotes: 3

Views: 3390

Answers (4)

LU RD
LU RD

Reputation: 34899

Iterate all members of the string, move the characters to the Result, but skip repeated spaces.

function DeleteRepeatedSpaces(const OldText: string): string;
var
  i,j,hi: Integer;
begin
  SetLength(Result,Length(OldText));
  i := Low(OldText);
  j := i;
  hi := High(OldText);
  while (i <= hi) do begin
    Result[j] := OldText[i];
    Inc(j);
    if (OldText[i] = ' ') then begin
      repeat  //Skip additional spaces
        Inc(i);
      until (i > hi) or (OldText[i] <> ' ');
    end
    else
      Inc(i);
  end;
  SetLength(Result,j-Low(Result));  // Set correct length
end;

The above code is rather fast (faster than any other contribution, so far).

Below is an even more optimized routine:

function DeleteRepeatedSpaces(const OldText: string): string;
var
  pO,pR: PChar;
begin
  SetLength(Result,Length(OldText));
  pR := Pointer(Result);
  pO := Pointer(OldText);
  while (pO^ <> '') do begin
    pR^ := pO^;
    Inc(pR);
    if (pO^ <> ' ') then begin
      Inc(pO);
      Continue;
    end;
    repeat // Skip additional spaces
      Inc(pO);
    until (pO^ = '') or (pO^ <> ' ');
  end;
  SetLength(Result,pR-Pointer(Result));
end;

Upvotes: 4

Alex James
Alex James

Reputation: 696

The following isn't wildly efficient, but possibly more so that processiing the string character by character because it doesn't require a new string allocation for each character in the output:

function RemoveDupSpaces(const Input : String) : String;
var
  P : Integer;
begin
  Result := Input;
  repeat
    P := Pos('  ', Result);  // that's two spaces
    if P > 0 then
      Delete(Result, P + 1, 1);
  until P = 0;
end;

Upvotes: 3

You can use something like this:

function DeleteRepeatedSpaces(const s: string):string;
var
  i:integer;
begin
  Result := '';
  for i := 1 to Length(S) do begin
    if not ((s[i]=' ') and (s[i-1]=' ')) then begin
      Result := Result + s[i];
    end;
  end;
end;

Delete two o more spaces contiguous in a string.

This string (without spaces):

The string have groups of spaces inside

return this:

The string have groups of spaces inside

This string (with spaces groups inside):

The   string  have       groups    of  spaces   inside

Return this:

The string have groups of spaces inside

Upvotes: -1

MBo
MBo

Reputation: 80187

Function based on the simplest state machine (DFA). Minimum of memory reallocations.
State is number of continuous spaces.
J is count of deleted spaces.

  function DeleteRepeatedSpaces(const s: string): string;
  var
    i, j, State: Integer;
  begin
    SetLength(Result, Length(s));
    j := 0;
    State := 0;

    for i := 1 to Length(s) do begin

      if s[i] = ' ' then
        Inc(State)
      else
        State := 0;

      if State < 2 then
        Result[i - j] := s[i]
      else
        Inc(j);

    end;

    if j > 0 then
        SetLength(Result, Length(s) - j);
  end;

Upvotes: 7

Related Questions