Solved

Replace multiple blanks in string to one blank

Posted on 2004-10-14
17
476 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 23

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
[Live Webinar] The Cloud Skills Gap

As Cloud technologies come of age, business leaders grapple with the impact it has on their team's skills and the gap associated with the use of a cloud platform.

Join experts from 451 Research and Concerto Cloud Services on July 27th where we will examine fact and fiction.

 
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 23

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 23

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

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

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

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Monitoring a network: why having a policy is the best policy? Michael Kulchisky, MCSE, MCSA, MCP, VTSP, VSP, CCSP outlines the enormous benefits of having a policy-based approach when monitoring medium and large networks. Software utilized in this v…
In this video you will find out how to export Office 365 mailboxes using the built in eDiscovery tool. Bear in mind that although this method might be useful in some cases, using PST files as Office 365 backup is troublesome in a long run (more on t…
Suggested Courses
Course of the Month8 days, 15 hours left to enroll

615 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