我想从字符串中删除所有特殊字符。允许的字符是AZ(大写或小写),数字(0-9),下划线(_)或点号(。)。
我有以下内容,它可以工作,但是我怀疑(我知道!)它不是很有效:
public static string RemoveSpecialCharacters(string str) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < str.Length; i++) { if ((str[i] >= '0' && str[i] <= '9') || (str[i] >= 'A' && str[i] <= 'z' || (str[i] == '.' || str[i] == '_'))) { sb.Append(str[i]); } } return sb.ToString(); }
最有效的方法是什么?正则表达式是什么样子?与普通的字符串操作相比如何?
将要清理的字符串会很短,通常长度在10到30个字符之间。
为什么您认为您的方法效率不高?实际上,这是最有效的方法之一。
您当然应该将字符读入局部变量,或者使用枚举数来减少数组访问的次数:
public static string RemoveSpecialCharacters(this string str) { StringBuilder sb = new StringBuilder(); foreach (char c in str) { if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '.' || c == '_') { sb.Append(c); } } return sb.ToString(); }
使这种方法高效的一件事是,它可以很好地扩展。执行时间将相对于字符串的长度。如果将它用在大字符串上没有令人讨厌的惊喜。
编辑: 我进行了一项快速的性能测试,使用24个字符串运行每个功能一百万次。结果如下:
原始功能:54.5毫秒。 我建议的更改:47.1毫秒。 设置StringBuilder容量的矿井:43.3毫秒。 正则表达式:294.4 ms。
编辑2:我在上面的代码中添加了AZ和az之间的区别。(我重新进行了性能测试,没有明显的区别。)
编辑3: 我测试了lookup + char []解决方案,它运行约13毫秒。
当然,要付出的代价是巨大查找表的初始化并将其保存在内存中。嗯,这不是很多数据,但是对于这样一个微不足道的功能来说却是很多…
private static bool[] _lookup; static Program() { _lookup = new bool[65536]; for (char c = '0'; c <= '9'; c++) _lookup[c] = true; for (char c = 'A'; c <= 'Z'; c++) _lookup[c] = true; for (char c = 'a'; c <= 'z'; c++) _lookup[c] = true; _lookup['.'] = true; _lookup['_'] = true; } public static string RemoveSpecialCharacters(string str) { char[] buffer = new char[str.Length]; int index = 0; foreach (char c in str) { if (_lookup[c]) { buffer[index] = c; index++; } } return new string(buffer, 0, index); }