【问题标题】:Delete numbers from a String从字符串中删除数字
【发布时间】:2012-06-05 23:56:35
【问题描述】:

我想知道如何从字符串中删除数字。我尝试使用 StringReplace,但不知道如何告诉函数我要替换数字。

这是我尝试过的:

StringReplace(mString, [0..9], '', [rfReplaceAll, rfIgnoreCase]);

【问题讨论】:

  • 嗯,Delphi XE 及以上版本支持正则表达式,可用于字符串替换。它在 RegularExpressions 和 RegularExpressionsCore 单元中
  • 好的,谢谢,我去看看。

标签: string delphi replace


【解决方案1】:

StringReplace 不接受集合作为第二个参数。也许有人会有更合适的方法,但这有效:

StringReplace(mString, '0', '', [rfReplaceAll, rfIgnoreCase]);
StringReplace(mString, '1', '', [rfReplaceAll, rfIgnoreCase]);    
StringReplace(mString, '2', '', [rfReplaceAll, rfIgnoreCase]);

等等

【讨论】:

  • 呸!你能说DRY(不要重复你自己)吗?抱歉,但我不得不将此作为对所提问题的可怕解决方案投反对票。
  • 同意.. 你至少可以循环.. for i := 0 to 9 do StringReplace(mString, I, '', [rfReplaceAll, rfIgnoreCase]);
  • 嘿,肯,放轻松! :-) “可怕吗?”是的,for 循环有优势。但是,有时,增加复杂性会增加错误。 John 的代码(除非他在我发布此代码后对其进行编辑)就是一个很好的例子:首先,它无法编译。假设他打算“i”是一个整数,那么正确的代码有点棘手。第二个参数应该是chr(ord('0') + i),不是吗?或者 for 循环应该是 ch := chr('0') 到 chr('9')。两者都增加了一些复杂性并且并没有真正直接回答他的问题,即如何使用 StringReplace。我认为 OP 可以按照您的建议轻松修改代码。
  • @RobertFrank 我们的两个代码片段都不起作用,因为 StringReplace 是一个函数 :) 也就是说,“可怕”在这里是一个强词......
【解决方案2】:

好吧,我已经厌倦了寻找已经构建的函数,所以我创建了自己的函数:

   function RemoveNumbers(const AValue: string): string;
   var
      iCar : Integer;
      mBuffer : string;
   begin
      mBuffer := AValue;

      for iCar := Length(mBuffer) downto 1 do
      begin
         if (mBuffer[iCar] in ['0'..'9']) then
            Delete(mBuffer,iCar,1);
      end;
      Result := mBuffer;
   end;

【讨论】:

  • 您的函数将失败,for 循环计数器被缓存,您正在 缩短循环中的字符串。
  • 但是您可以通过恢复删除顺序来解决此问题(改用for ... downto)。只记得string 中的字符是从1 索引的,而不是从0 索引的。
  • 我更喜欢尼克的版本。他编写的代码更干净、更易读,而且不太可能出错。而你的使用更多的内存,可能更慢。在我传入 'a123908908203809....' (一个 2 GB 的字符串,其中只有第一个字符是非数字)字符串的病态情况下,他仍然可以工作。甜的。你的?不太好。在相反的情况下,使用中等大小的字符串,并且只删除一个数字,您的可能会更快,内存使用差异可能无关紧要,但它的可读性仍然较低。
【解决方案3】:

简单但有效。可以进行优化,但应该首先为您提供所需的内容:

function RemoveNumbers(const aString: string): string;
var
  C: Char;
begin
  Result := '';
  for C in aString do begin
      if not CharInSet(C, ['0'..'9']) then
      begin
        Result := Result + C;
      end;
    end;
end;

【讨论】:

  • 同意。虽然我是正则表达式的忠实粉丝,但 Nick 对这个特定问题的解决方案要快得多。任何更复杂的事情,我都会立即使用 RegEx!
  • 您可能会考虑使用TStringBuilder 来避免在附加字符时进行不必要的内存重新分配:SB := TStringBuilder.Create(Length(aString));... SB.Append(C); ... Result := SB.ToString; SB.Free; 这类似于 Wouter 答案的概念,只是使用了一个类包装器。
【解决方案4】:

相当快速的就地版本。

procedure RemoveDigits(var s: string);
var
  i, j: Integer;
  pc: PChar;
begin
  j := 0;
  pc := PChar(@s[1]);
  for i := 0 to Length(s) - 1 do
    if pc[i] in ['0'..'9'] then 
               //if CharInSet(pc[i], ['0'..'9']) for Unicode version
      Inc(j)
    else
      pc[i - j] := pc[i];
  SetLength(s, Length(s) - j);
end;

【讨论】:

  • +1 用于就地替换,如果原始字符串很大,这种方法的内存效率会更高。任何 str := str + ?或其他生成临时字符串的方法可以非常快速地建立大量内存占用,当在大型数据集(几兆)上使用简单的转换例程(十六进制到 bin、base64 等)时,我遇到过这种情况
【解决方案5】:

这与 Nick 的版本具有相同的输出,但使用短字符串时速度是其 3 倍以上。文字越长,差异越大。

function RemoveNumbers2(const aString: string): string;
var
  C:Char; Index:Integer;
begin
  Result := '';
  SetLength(Result, Length(aString));
  Index := 1;
  for C in aString do
    if not CharInSet(C, ['0' .. '9']) then
    begin
      Result[Index] := C;
      Inc(Index);
    end;
  SetLength(Result, Index-1);
end;

如果没有必要,不要浪费宝贵的 CPU 周期。

【讨论】:

    【解决方案6】:

    使用这个

    function RemoveNonAlpha(srcStr : string) : string;
    const
    CHARS = ['0'..'9'];
    var i : integer;
    begin
    result:='';
    for i:=0 to length(srcStr) do
    if  (srcstr[i] in CHARS) then
    result:=result+srcStr[i];
    end   ;
    

    你可以这样称呼它

    edit2.text:=RemoveNonAlpha(edit1.text);

    【讨论】:

    • 这行得通,但功能颠倒了:它正在删除 alpha 字符:p
    猜你喜欢
    • 2013-06-24
    • 2017-05-21
    • 1970-01-01
    • 2016-07-26
    • 2013-09-18
    • 2011-11-22
    相关资源
    最近更新 更多