如何删除角色周围的空间?

时间:2011-11-09 14:47:31

标签: string delphi

说我有以下字符串:

s := 'This , is,       the Delphi  ,    World!';

我想要以下输出:

Result := 'This,is,the Delphi,World!';

基本上我需要一个例程,如果它们出现在逗号字符(这是我的分隔符)之前或之后,它会删除 ALL 空格 ON 的出现,在其他字符之间留下完整的空格词语的

非常感谢任何帮助。

您如何看待这个解决方案?

function RemoveSpacesAroundDelimiter(var aString: string; aDelimiter:
    string): string;
begin
  while AnsiContainsText(aString, aDelimiter + ' ') do
    begin
    aString := StringReplace(aString, ', ', aDelimiter, [rfReplaceAll, rfIgnoreCase]);
    end;

  while AnsiContainsText(aString, ' ' + aDelimiter) do
    begin
    aString := StringReplace(aString, ' ' + aDelimiter, aDelimiter, [rfReplaceAll, rfIgnoreCase]);
    end;

  Result := aString;
end;

感谢

的Fabio

11 个答案:

答案 0 :(得分:9)

听起来像是TStringList的任务。

function UltraTrim(Value: string): string;
var
  sl: TStringList;
  i: Integer;
begin
  sl := TStringList.Create;
  try
    // Prevent the stringlist from using spaces as delimiters too.
    sl.StrictDelimiter := True;

    // Set the comma separated text.
    sl.CommaText := Value;

    // Trim each item.
    for i := 0 to sl.Count -1 do
      sl[i] := Trim(sl[i]);

    // Concat back to comma separated string.
    Result := sl.CommaText;
  finally
    sl.Free;
  end;

end;

答案 1 :(得分:4)

快速版可能是:

function RemoveSpacesAroundDelimiter(const aString: string; aDelimiter: char = ','): string;
var S, D, D2: PChar;
begin
  SetLength(result,length(aString));
  if aString<>'' then
  begin
    S := pointer(aString);
    D := pointer(result);
    while S^<>#0 do
    begin
      if S^=' ' then
      begin
        D2 := D;
        repeat
          inc(S);
          D^ := ' ';
          inc(D);
        until S^<>' ';
        if S^=#0 then
          break;
        if S^=aDelimiter then
          D := D2; // trim spaces before comma
      end;
      D^ := S^;
      if (S[0]=aDelimiter) and (S[1]=' ') then
        repeat inc(S) until S^<>' ' else // trim spaces after comma
        inc(S);
      inc(D);
    end;
    SetLength(result,D-pointer(result));
  end;
end;

一些测试代码:

  assert(RemoveSpacesAroundDelimiter('one two,three')='one two,three');
  assert(RemoveSpacesAroundDelimiter('one two , three')='one two,three');
  assert(RemoveSpacesAroundDelimiter('one,two,three')='one,two,three');
  assert(RemoveSpacesAroundDelimiter('one   ,   two,  three')='one,two,three');

答案 2 :(得分:3)

将字符逐个复制到目标缓冲区中,但查找空格和分隔符,并记住将非空格字符复制到的最后位置。如果您看到一个空格,并且您复制的最后一个非空格是分隔符,则跳过该空格。如果它是一个空格,并且您复制的最后一个字符不是分隔符,则将其复制到目标,但请记住您添加的最后一个非空格。这样,如果您稍后看到分隔符,则可以返回并覆盖它。

function RemoveSpacesAroundDelimiter(const AString: string; ADelimiter: Char): string;
var
  c: Char;
  dest: Integer;
  LastNonSpace: Integer;
  HaveDelimiter: Boolean;
begin
  Assert(ADelimiter <> ' ');
  SetLength(Result, Length(AString));
  dest := 1;
  LastNonSpace := 0;
  HaveDelimiter := False;
  for c in AString do begin
    if (c = ' ') and HaveDelimiter then
      continue; // Skip this character

    if c = ADelimiter then begin
      dest := LastNonSpace + 1;
      HaveDelimiter := True;
    end else
      HaveDelimiter := False;
    Result[dest] := c;
    if c <> ' ' then
      LastNonSpace := dest;
    Inc(dest);
  end;
  SetLength(Result, dest - 1);
end;

答案 3 :(得分:3)

如果您使用的是Delphi XE或更高版本,则可以使用正则表达式在一行代码中轻松完成此操作。

program regex;

{$APPTYPE CONSOLE}

uses
  RegularExpressions;

const
  Input = 'This , is,       the Delphi  ,    World!';

begin
  Writeln(TRegEx.Replace(Input, ' *, *', ','));
  Readln;
end.

当然,这不是所提供解决方案中运行速度最快的,但也许对您来说无关紧要。

答案 4 :(得分:1)

您可以使用正则表达式。您希望找到前面或后跟任意数量空格的分隔符,并将其全部替换为分隔符的单个副本。

function RemoveSpacesAroundDelimiter(const AString: string; const ADelimiter: string): string;
var
  re: TPerlRexEx;
begin
  re := TPerlRegEx.Create;
  try
    re.RegEx := '\s*' + TPerlRegEx.EscapeRegExChars(ADelimiter) + '\s*';
    re.Subject := AString;
    re.Replacement := TPerlRegEx.EscapeRegExChars(ADelimiter);
    re.ReplaceAll;
    Result := re.Subject;
  finally
    re.Free;
  end;
end;

较新的Delphi版本可以使用内置的RegularExpressionCore单元。较旧的版本可以使用等效的PerlRegEx unit from Jan Goyvaerts

Mick之前发布的an answer证明了这一点,但是他删除了它,因为他得到了正则表达式错误(删除所有空格而不仅仅是与分隔符相邻的空格)。

答案 5 :(得分:1)

更简单,最简单的方法是使用正则表达式。您需要的最后一件事是一个巨大的复杂代码块来解决这样一个简单的问题。不幸的是我现在没有Delphi,我无法测试这段代码,但是如果它不是这样的话,它非常接近:

s := 'This , is,       the Delphi  ,    World!';
RegEx := TRegEx.Create('[ ]*,[ ]*');
CleanStr := RegEx.Replace(s, ',');

答案 6 :(得分:1)

我有此解决方案:

slValores.DelimitedText := StringReplace(sListSummary,' ','',[rfReplaceAll]);

答案 7 :(得分:0)

我认为这值得补充,因为它适用于早期版本的Delphi,其中stringlist解决方案(我喜欢)不会。

我相信它的速度相当快,阅读和理解起来相当简单。

function TForm1.UltraTrim(const InString : String; Delim : Char) : String;
var
  Buf : String;
  i : Integer;
  Token : String;
begin
  Result := '';
  if Trim(InString) <> '' then begin
    i := 1;
    Buf := StringReplace(InString, Delim, #0, [rfReplaceAll]) + #0;
    while i < Length(Buf) do begin
      Token := StrPas(@Buf[i]);
      i := i + Length(Token) + 1;
      Result := Result + Delim + Trim(Token);
    end;
    Result := Copy(Result,2,Length(Result));
  end;
end;

答案 8 :(得分:0)

使用Jedi代码库,@ GolezTrol的回答可以使用单行重新编写。

function UltraTrim(Value: string): string;
begin
  Result := JclStringList.Split(Value, ',').Trim.Join(',')
end;

答案 9 :(得分:0)

使用此功能:

function MBTrim(iStr :string):string;
const CTc= 3{Conditions Count};
      CT :array[0..(CTc-1),0..1]of string= ( (' ,', ','), (', ', ','), ('  ', ' ') );
var   i  :Integer;
begin
  for i := 0 to CTc-1 do while Pos(CT[i,0], iStr) > 0 do
    iStr:= StringReplace(iStr, CT[i,0], CT[i,1], [rfReplaceAll, rfIgnoreCase]);
  Result:= Trim(iStr);
end;

您可以简单地添加其他条件。

例如,我添加(' ', ' ')来转换单词之间的空格,如:

'This , is,       the       Delphi  ,    World!'

答案 10 :(得分:-2)

再次改变。

  while (pos(', ',s)>0) or (pos(' ,',s)>0) do   begin
    s := StringReplace(s, ', ', ',', [rfReplaceAll]);
    s := StringReplace(s, ' ,', ',', [rfReplaceAll]);   end;

确定所有Delphi版本。