我想从字符串中删除所有特殊字符。允许输入A-Z(大写或小写)、数字(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个字符之间。
我觉得你的算法很有效。它是O(n),并且只查看每个字符一次。除非你在检查它们之前神奇地知道它们的值,否则你不会比这更好。
但是,我将把StringBuilder的容量初始化为字符串的初始大小。我猜您认为的性能问题来自内存重新分配。
旁注:检查A-z并不安全。你要包括[,\,],^,_和'…
旁注2:为了获得额外的效率,将比较按顺序排列,以减少比较的数量。(在最坏的情况下,你说的是8个比较,所以不要想太多。)这随你的预期输入而变化,但一个例子可以是:
if (str[i] >= '0' && str[i] <= 'z' &&
(str[i] >= 'a' || str[i] <= '9' || (str[i] >= 'A' && str[i] <= 'Z') ||
str[i] == '_') || str[i] == '.')
旁注3:如果出于某种原因,你真的需要它更快,那么switch语句可能更快。编译器应该为你创建一个跳转表,结果只有一个比较:
switch (str[i])
{
case '0':
case '1':
.
.
.
case '.':
sb.Append(str[i]);
break;
}
如果你使用的是动态字符列表,LINQ可以提供一个更快更优雅的解决方案:
public static string RemoveSpecialCharacters(string value, char[] specialCharacters)
{
return new String(value.Except(specialCharacters).ToArray());
}
我将这种方法与之前的两种“快速”方法(发行版编译)进行了比较:
字符数组解决方案由LukeH - 427毫秒
StringBuilder解决方案- 429毫秒
LINQ(这个答案)- 98毫秒
注意,算法略有修改-字符作为数组传入,而不是硬编码,这可能会有轻微的影响(即/其他解决方案将有一个内部for循环来检查字符数组)。
如果我使用LINQ where子句切换到硬编码的解决方案,结果是:
字符数组解决方案- 7ms
StringBuilder解决方案- 22ms
LINQ - 60毫秒
如果您计划编写一个更通用的解决方案,而不是硬编码字符列表,那么可能值得考虑LINQ或经过修改的方法。LINQ绝对能给你简洁、高可读性的代码——甚至比Regex更好。