Delphi中移除字符串非数字字符的最优方案及内置函数查询
Delphi移除字符串中非数字字符的最佳实践
有没有内置函数?
Delphi的标准VCL/RTL库没有直接提供移除所有非数字字符的内置函数,你需要自己实现或者基于现有API封装。
现有三种实现的优缺点
1. 正向遍历拼接字符串
function RemoveNonNumericChars(const s: string): string; begin Result := ''; for var i := 1 to Length(s) do begin if s[i] in ['0'..'9'] then Result := Result + s[i]; end; end;
- 优点:逻辑简单直观,易理解维护
- 缺点:每次字符串拼接都会触发内存重新分配(Delphi字符串为不可变类型),长字符串场景下性能下降明显,还会产生内存碎片。
2. 反向遍历删除非数字字符
function RemoveNonNumericChars(const s: string): string; begin Result := s; for var i := Length(Result) downto 1 do begin if not(Result[i] in ['0'..'9']) then Delete(Result, i, 1); end; end;
- 优点:基于输入副本修改,无需额外创建空字符串;反向遍历避免了删除字符后的索引偏移问题
- 缺点:
Delete操作会移动后续字符,非数字字符较多时,频繁的内存移动会拖慢速度,长字符串场景下性能一般。
3. 正则表达式替换
function RemoveNonNumericChars(const s: string): string; begin var RegEx := TRegEx.Create('[^0-9]'); Result := RegEx.Replace(s, ''); end;
- 优点:代码最简洁,正则规则灵活(若后续需调整匹配逻辑,比如保留小数点、正负号,修改正则即可)
- 缺点:性能最差——正则引擎初始化、模式编译、匹配遍历的开销远高于直接字符遍历,简单数字过滤场景属于过度设计。
更优的实现:预分配内存的正向遍历
针对第一个函数的性能短板,我们可以先统计数字字符数量,一次性分配足够内存,再填充字符,这是目前最快的实现方式:
function RemoveNonNumericChars(const s: string): string; var i, Count: Integer; begin Count := 0; // 先统计数字字符总数 for i := 1 to Length(s) do if s[i] in ['0'..'9'] then Inc(Count); // 预分配目标字符串内存 SetLength(Result, Count); Count := 0; // 填充数字字符 for i := 1 to Length(s) do if s[i] in ['0'..'9'] then begin Inc(Count); Result[Count] := s[i]; end; end;
这个版本彻底避免了多次内存分配,所有操作都在预分配的内存中直接完成,处理长字符串时性能优势尤为显著。
如果使用Delphi 10.3+,还可以借助System.SpanUtils单元的Span进一步优化索引操作开销:
uses System.SpanUtils; function RemoveNonNumericChars(const s: string): string; var InputSpan: TSpan<char>; OutputSpan: TSpan<char>; OutputIdx: Integer; begin InputSpan := s.AsSpan; OutputIdx := 0; // 统计数字数量 for var C in InputSpan do if C in ['0'..'9'] then Inc(OutputIdx); SetLength(Result, OutputIdx); OutputSpan := Result.AsSpan; OutputIdx := 0; // 填充数字字符 for var C in InputSpan do if C in ['0'..'9'] then begin OutputSpan[OutputIdx] := C; Inc(OutputIdx); end; end;
最佳/最快方法总结
- 最快性能:优先选择预分配内存的正向遍历实现,内存分配和字符操作开销最小,适配所有场景,尤其是长字符串处理。
- 代码简洁性:若对性能要求不高(比如短字符串、低调用频率),正则表达式版本最省心。
- 折中方案:反向删除版逻辑简单,性能略优于原始正向拼接,但仍不如预分配版本。
内容的提问来源于stack exchange,提问作者Shaun Roselt
相关产品推荐
相关产品推荐

