如何删除Delphi字符串中的数字

3

我有一个字符串,我设置了选择字母的坐标,但有时它们会混乱并与数字一起出现,如何使得例如'105DYUDXB28DYU13'变为'DYUDXBDYU'

tmpT.Put:=Trim(MidStr(S,8,6))+Trim(MidStr(S,37,3));

enter image description here


遍历字符串的字符,构建一个新的字符串。丢弃你不想要的字符。 - David Heffernan
或者如果您想使其更加灵活(例如使用用户输入的模式),请使用正则表达式。 - Victoria
@Victoria:虽然正则表达式有它们的用途,但我不认为这是其中之一。正则表达式在性能上远不如简单的循环,在将一个字符串复制到另一个字符串时省略数字。换句话说:如果你有一个问题,并使用正则表达式来解决它,那么你就会有两个问题了。<g> - Rudy Velthuis
@Rudy,当然。但对于用户输入的模式来说是很好的(至少对于受过教育的用户来说是这样的 :))。 - Victoria
抱歉,将此标记为从字符串中删除数字的重复问题,但意识到没有很好地涵盖Delphi-7限制的答案。 - LU RD
@LURD,该链接中有适用于Delphi 7的答案。 - Remy Lebeau
2个回答

6
一个性能良好的解决方案如下(使用Character):
function RemoveNumbers(const AString: string): string;
var
  i, j: integer;
begin
  SetLength(result, AString.Length);
  j := 0;
  for i := 1 to AString.Length do
    if not AString[i].IsDigit then
    begin
      inc(j);
      result[j] := AString[i];
    end;
  SetLength(result, j);
end;

该函数使用Delphi 7之后引入的几个语言和库特性。要在Delphi 7中使其正常工作,您需要稍微重新编写它:

function RemoveNumbers(const AString: string): string;
var
  i, j: integer;
begin
  SetLength(result, Length(AString));
  j := 0;
  for i := 1 to Length(AString) do
    if not (AString[i] in ['0'..'9']) then
    begin
      inc(j);
      result[j] := AString[i];
    end;
  SetLength(result, j);
end;

细则:TCharHelper.IsDigit是Unicode感知的,因此对于所有Unicode数字它都返回true。例如,对于٣(U+0663:阿拉伯-印度数字三)、੪(U+0A6A:果鲁穆奇数字四)、௫(U+0BEB:泰米尔数字五)、៥(U+17E5:高棉数字五)和᠗(U+1817:蒙古数字七),它将返回true。
如果您只想将字符'0'..'9'视为数字,则可以使用Delphi 7测试的现代化版本:
if not CharInSet(AString[i], ['0'..'9']) then

不确定是否可以描述为完美。循环两次并进行单个分配可能会更好。由于问题不涉及性能,我会忽略这个方面。答案肯定应该是针对Delphi 7的。此外,Unicode标准是否定义了超过10个数字? - David Heffernan
2
@DavidHeffernan:确实,IsDigit将会把不仅仅是0..9的字符视为数字。但所需的语义取决于实际情况,我无法了解任何详细信息。(而且我认为在SO上提供一个“现代”的解决方案和适用于指定Delphi版本的解决方案是一个好的做法,以便其他可能看到该问题的人受益。) - Andreas Rejbrand
是的,你说得对,但基于安德烈亚斯所做出的贡献,我们都应该感谢他。 - delphi
截断是另一种堆分配操作。它们可能非常昂贵,特别是与刚刚进入缓存的内存访问相比。我不知道哪个更快,这取决于使用情况和可能的其他因素。但“完美”很难证明。 - David Heffernan
@DavidHeffernan:感谢您的澄清。我已相应地更改了答案。 - Andreas Rejbrand
显示剩余3条评论

0

同时使用过程和变量参数编写代码:

procedure RemoveNumbers(var Text: String);
var
    Index: Integer;
begin
    for Index := Length(Text) downto 1 do
         if Text[Index] in ['0'..'9']
         then Text := Copy(Text, 1, Index - 1) + Copy(Text, Index + 1, Length(Text) - Index);
end;

var
    Text: String;

begin
    Text := '105DYUDXB28DYU13';
    RemoveNumbers(Text);
    WriteLn(Text);
end.

就性能而言,这远非最佳选择。它将导致大量的内存分配和复制。 - Andreas Rejbrand

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接