我一开始并不相信Bittercode所说的LINQ比正则表达式更高效,于是我进行了一些测试以确保这点。
以下是三个例子:
Dim _invalidChars As Char() = New Char() {"j"c, "a"c, "n"c}
Dim _textToStrip As String = "The quick brown fox jumps over the lazy dog"
Private Sub btnStripInvalidCharsLINQ_Click(sender As System.Object, e As System.EventArgs) Handles btnStripInvalidCharsLINQ.Click
Dim stripped As String = String.Empty
Dim sw As Stopwatch = Stopwatch.StartNew
For i As Integer = 0 To 10000
stripped = _textToStrip.Where(Function(c As Char) Not _invalidChars.Contains(c)).ToArray
Next
sw.Stop()
lblStripInvalidCharsLINQ.Text = _stripped & " - in " & sw.Elapsed.TotalMilliseconds & " ms"
End Sub
Private Sub btnStripInvalidCharsFOR_Click(sender As System.Object, e As System.EventArgs) Handles btnStripInvalidCharsFOR.Click
Dim stripped As String = String.Empty
Dim sw As Stopwatch = Stopwatch.StartNew
stripped = _textToStrip
For i As Integer = 0 To 10000
For Each c As Char In _invalidChars
stripped = stripped.Replace(c, "")
Next
Next
sw.Stop()
lblStipInvalidcharsFor.Text = stripped & " - in " & sw.Elapsed.TotalMilliseconds & " ms"
End Sub
Private Sub btnStripInvalidCharsREGEX_Click(sender As System.Object, e As System.EventArgs) Handles btnStripInvalidCharsREGEX.Click
Dim stripped As String = String.Empty
Dim sw As Stopwatch = Stopwatch.StartNew
For i As Integer = 0 To 10000
stripped = Regex.Replace(_textToStrip, "[" & New String(_invalidChars) & "]", String.Empty)
Next
sw.Stop()
lblStripInvalidCharsRegex.Text = stripped & " - in " & sw.Elapsed.TotalMilliseconds & " ms"
End Sub
结果如下:
结果:
![性能测试结果](https://istack.dev59.com/SqUvd.webp)
因此,使用字符串替换的 for 循环的性能优于所有其他方法。
因此,我会创建一个字符串对象的扩展函数。
Module StringExtensions
<Extension()> _
Public Function ReplaceAll(ByVal InputValue As String, ByVal chars As Char(), replaceWith As Char) As String
Dim ret As String = InputValue
For Each c As Char In chars
ret = ret.Replace(c, replaceWith)
Next
Return ret
End Function
那么你可以在一行中使用这个函数,写法简单易懂:
_textToStrip.ReplaceAll(_invalidChars, CChar(String.Empty))
编辑(十年后):
我再次需要尽可能快地完成这个任务。
这一次我编写了一个真正的性能测试(benchmarkdotnet)。
我使用了 net6.0。
代码可在 github 上找到:https://github.com/j-dc/stackoverflow_1332454
[SimpleJob(RuntimeMoniker.Net60)]
[RPlotExporter]
public class RemoveChars {
private static readonly char[] _invalidChars = new[] { 'j', 'a', 'n' };
private static readonly string _textToStrip = "The quick brown fox jumps over the lazy dog";
private static readonly HashSet<char> _invalidHash = new(new[] { 'j', 'a', 'n' });
[Benchmark]
public string Linq() {
return new string(_textToStrip.Where(x => !_invalidChars.Contains(x)).ToArray());
}
[Benchmark]
public string ForEach() {
string ret = _textToStrip;
foreach(char c in _invalidChars) {
ret = ret.Replace(Convert.ToString(c), "");
}
return ret;
}
[Benchmark]
public string Regexer() {
return Regex.Replace(_textToStrip, $"[{new string(_invalidChars) }]", string.Empty);
}
[Benchmark]
public string Hasher() {
return new string(_textToStrip.Where(x => _invalidHash.Contains(x)).ToArray());
}
[Benchmark]
public string Splitting() {
return string.Join(string.Empty, _textToStrip.Split(_invalidChars, StringSplitOptions.RemoveEmptyEntries));
}
[Benchmark]
public string Aggregate() {
return _invalidChars.Aggregate(_textToStrip, (c1, c2) => c1.Replace(Convert.ToString(c2), ""));
}
}
}
结果:
方法 |
平均值 |
误差 |
标准偏差 |
LinqToArray |
635.2 纳秒 |
12.20 纳秒 |
11.42 纳秒 |
ForEach |
119.0 纳秒 |
1.58 纳秒 |
1.40 纳秒 |
Regexer |
392.0 纳秒 |
7.38 纳秒 |
8.50 纳秒 |
Hasher |
402.0 纳秒 |
6.04 纳秒 |
5.65 纳秒 |
分割法 |
109.8 纳秒 |
1.84 纳秒 |
1.72 纳秒 |
Aggregate |
136.6 纳秒 |
2.62 纳秒 |
2.45 纳秒 |