似乎缺少一个选项,然后您几乎完全被覆盖。对于仅删除两个字符,Replace.Replace 的使用是最快的,紧随其后的是数组操作和字符串生成器。
Linq Where 和 string.Join 的使用使一切都变慢了一点,尽管这并不重要。
您会惊讶地发现 Regex(至少在 .NET 4.5 下)并不像您预期的那么慢。它甚至比使用 Linq 还要快。也许如果您使用编译表达式或委托,您也许可以加快 Linq 表达式的速度。
当您需要替换字符串中的较大部分或多个字符而不是两个字符时,统计信息可能会发生变化。
static void Main(string[] args)
{
string str = "123456#23876587234687237*723547623547523745273#";
Console.WriteLine("Join+Where");
Test(s => String.Join("",s.Where(char.IsDigit)), str);
Console.WriteLine("ArrayOperation");
Test(s => new string(Array.FindAll(s.ToCharArray(), char.IsDigit)), str);
Console.WriteLine("Join+Select");
Test(s => string.Join("", s.Select(r=> char.IsDigit(r) ? r.ToString():"")), str);
Console.WriteLine("ReplaceReplace");
Test(s => s.Replace("*", "").Replace("#", ""), str);
Console.WriteLine("Regex");
Test(s => Regex.Replace(s, "[#*]", ""), str);
Console.WriteLine("Regex");
Regex rx = new Regex("[#*]", RegexOptions.Compiled);
rx.Match(""); // Precompile for better results
Test(s => rx.Replace(s, ""), str);
Console.WriteLine("StringBuilder");
Test(s => new StringBuilder(s).Replace("*", "").Replace("#", "").ToString(), str);
Console.ReadLine();
}
public static void Test(Func<string,string> proposedSolution, string input)
{
GC.Collect();
GC.WaitForPendingFinalizers();
Thread.Sleep(5000);
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 1000; i++)
{
string val = proposedSolution(input);
Debug.Write(val);
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
}
“123456#23876587234687237*723547623547523745273#”的输出如下(您会注意到,如果正确使用正则表达式,它并不像人们让您相信的那么慢:
Join+Where
88
ArrayOperation
25
Join+Select
45
ReplaceReplace
18
Regex
39
Regex+Compiled
41
StringBuilder
19
当您需要替换的不仅仅是数字以外的所有内容时,这可能会变得更有趣。或者更具体地说是“#”和“*”。但最终,创建一个简单的测试,然后选择最容易理解和执行的方法可能是最好的解决方案。
需要指出的一件事:并非所有提供的解决方案都做同样的事情。虽然有些只保留数字,但另一些则专门从给定输入中删除两个字符。对于您的示例,这两个选项似乎都是有效的,但了解差异很重要。
使用 LINQ 仅删除 # 和 * 的相同选项:
char[] Removechars = new[] { '#', '*' };
Console.WriteLine("Join+Where");
Test(s => String.Join("", s.Where(c => !Removechars.Contains(c))), str);
Console.WriteLine("ArrayOperation");
Test(s => new string(Array.FindAll(s.ToCharArray(), c => !Removechars.Contains(c))), str);
Console.WriteLine("Except");
Test(s => new string(s.ToCharArray().Except(Removechars).ToArray()), str);
Console.WriteLine("Join+Select");
Test(s => string.Join("", s.Select(c => !Removechars.Contains(c) ? c.ToString():"")), str);
这些选项都比使用 IsDigit 或 !IsDigit 慢。