Solved

Replace multiple blanks in string to one blank

Posted on 2004-10-14
17
474 Views
Last Modified: 2010-04-05
Hi there,

I have a string which is build up like this:

This     is        a   string

I need to remove all redundant blanks in this string. So if the string contains more then one blank (space) in a row, they should be decreased to one. This situation can occure multiple times in the same string. The result should be:

This is a string

Please provide me with a function to accomplish this.
The solution with the smallest code gets the points.

Thanks a lot, Stef
0
Comment
Question by:Delphiwizard
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 3
  • 3
  • +4
17 Comments
 
LVL 11

Expert Comment

by:robert_marquardt
ID: 12306471
var
  S, Temp: string;
begin
  // S contains string to reduce
  Temp := S;
  repeat
    S := Temp;
    Temp := StringReplace(S, '  ', ' ', [rfReplaceAll]);
  until S = Temp;
end;
0
 
LVL 22

Expert Comment

by:Ferruccio Accalai
ID: 12306555
procedure TForm1.Button1Click(Sender: TObject);
function MyTrim(const S: string): string;
var
  I, L: Integer;
  A: String;
  got: Boolean;
begin
  A := '';
  L := Length(S);
  for i := 1 to L do begin
  If (S[I] <> ' ') then
  begin
  Got := False;
  A := a + s[i];
  end else
   If not Got then
      Begin
         a := a+ ' ';
         Got := True;
      end;
   end;
   Result := A;

end;
begin
Label1.Caption := MyTrim('This     is     a     string');
end;
0
 
LVL 14

Expert Comment

by:DragonSlayer
ID: 12306605
my version:

function RemoveRedundantSpaces(const S: string): string;
var
  sList: TStringList;
  i: Integer;
begin
  sList := TStringList.Create;
  Result := '';
  with sList do
  try
    Text := StringReplace(S, ' ', #13, [rfReplaceAll]);
    for i := 0 to Count - 1 do
      if Strings[i] <> '' then
        Result := Result + Strings[i] + ' ';
    Result := Trim(Result);
  finally
    Free;
  end;
end;

to use it:

Label1.Caption := RemoveRedundantSpace('This       is        a           string');
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 14

Expert Comment

by:DragonSlayer
ID: 12306610
note:

shortest note doesn't mean most efficient ;-)
0
 
LVL 14

Expert Comment

by:DragonSlayer
ID: 12306612
PS: Of course, neither was I saying that mine was the most efficient :-p
0
 
LVL 1

Expert Comment

by:NickRyan
ID: 12306630
This routine will strip out all of the multiple spaces in the string in only one pass (unlike the shorter but less efficient "StringReplace" example).

function StripMultiSpaces( const AString:string ):string;
var
  Index:integer;
  OnSpace:boolean;
begin
  Result := '';
  OnSpace := False;
  for Index := 1 to Length(AString) do begin
    if (AString[Index] = ' ') then begin
      if not OnSpace then Result := Result + AString[Index];
    end else begin
      Result := Result + AString[Index];
    end; {if}
    OnSpace := (AString[Index] = ' ');
  end; {for}
end;

0
 
LVL 1

Expert Comment

by:NickRyan
ID: 12306640
Oops, Ferruccio68's algorithm is pretty much the same as the one I just posted (his uses more local variables though).
0
 
LVL 17

Expert Comment

by:geobul
ID: 12306675
Hi,

My version:

function RemoveRedundantSpaces(const S: string): string;
var
  Len: integer;
  i,j: integer;
  Former: char;
begin
  result := S;
  Len := Length(S);
  Former := S[1];
  j := 2;
  for i := 2 to Len do begin
    if (S[i] = ' ') then begin
      if (not (Former = ' ')) then begin
        result[j] := S[i];
        Inc(j);
      end;
    end else begin
      result[j] := S[i];
      Inc(j);
    end;
    Former := S[i];
  end;
  SetLength(result, j);
end;

Regards, Geo
0
 
LVL 14

Accepted Solution

by:
Pierre Cornelius earned 500 total points
ID: 12306708
Try this:

function MergeSpaces(s: string):string;
var i: integer; Merge: Boolean;
begin
  Merge:= false;
  for i:= 0 to Length(s)-1 do
  begin
    if (s[i+1] <> ' ') then Merge:= false;
    if NOT Merge then result:= result + s[i+1];
    Merge:= (s[i+1] = ' ');
  end;
end;
0
 

Author Comment

by:Delphiwizard
ID: 12306739
It is quite important that the function is fast too ofcourse.
So a onepass through the string is very much appreciated.
0
 
LVL 17

Expert Comment

by:geobul
ID: 12307796
My solution is ten times faster than the accepted one :-(
0
 
LVL 22

Expert Comment

by:Ferruccio Accalai
ID: 12307818
ehhh Geo, that's the life :)))

F68 ;-)
0
 
LVL 1

Expert Comment

by:NickRyan
ID: 12307859
...the accepted answer also tramples off the end of the string if you give it a single character. That said, it isn't really an issue as it only tramples onto the #0 terminating the string.
0
 
LVL 17

Expert Comment

by:geobul
ID: 12308005
F68, your function is the second best of the six. Testing agains huge strings my function becomes more than 50 times faster compared to the accepted one.

Best regards,
0
 
LVL 22

Expert Comment

by:Ferruccio Accalai
ID: 12308050
I see geo, and i agree with you, but you and me know how to test and choose the best one. Maybe he did like the accepted one just for the 'less code' without give a try to every posted code...

Every man is different from each other man, that's why i said 'that's the life' :)))

F68 ;-)
0
 
LVL 17

Expert Comment

by:geobul
ID: 12308234
Sure, F68. I put effords on testing because Delphiwizard said:
>It is quite important that the function is fast too ofcourse.
and posted the results of the tests for the eventual future readers ;-)
0
 

Author Comment

by:Delphiwizard
ID: 12309787
The reason that I choose this one is probably because it worked fine and it has not to many lines of code.
If the other code of geobul is faster, that I don't know.
If I was smart enough to think of the proposed solutions and be able to determine which is faster then it probably would have chosen different. I try to choose better next time.
Thanks anyway for your input.
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
I've attached the XLSM Excel spreadsheet I used in the video and also text files containing the macros used below. https://filedb.experts-exchange.com/incoming/2017/03_w12/1151775/Permutations.txt https://filedb.experts-exchange.com/incoming/201…

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question