我可以多快地替换字符串中的字符?
因此,这个问题的背景是:我们有几个应用程序通过套接字相互通信并与客户端的应用程序通信。这些套接字消息包含不可打印的字符(例如chr(0)),需要用预定的字符串替换(例如“{Nul}”},因为套接字消息保存在日志文件中。每条日志消息都需要替换字符。
现在我开始阅读this MSDN link的这个小冒险,我从这个网站的另一篇文章中找到了这个。
我们当天使用的当前方法...在一天开始时...使用StringBuilder检查所有可能的替换,例如......
Public Function ReplaceSB(ByVal p_Message As String) As String
Dim sb As New System.Text.StringBuilder(p_Message)
sb.Replace(Chr(0), "{NUL}")
sb.Replace(Chr(1), "{SOH}")
Return sb.ToString
End Function
现在正如博客文章指出的那样离开StringBuilder并使用string.replace确实会产生更快的结果。 (实际上,使用StringBuilder是整天这样做的最慢的方法。)
p_Message = p_Message.Replace(Chr(0), "{NUL}")
p_Message = p_Message.Replace(Chr(1), "{SOH}")
知道不是每条消息都需要经历这个过程,我认为这样可以节省时间,而不必处理那些可能遗漏的消息。因此,使用正则表达式我首先搜索字符串,然后确定是否需要处理它。这与使用string.replace大致相同,基本上是节省不处理所有字符串的时间,但是用正则表达式检查所有字符串会浪费时间。
然后建议尝试使用一些匹配其索引的数组与旧的和新的并使用它来处理消息。所以它会是这样的......
Private chrArray() As Char = {Chr(0), Chr(1)}
Private strArray() As String = {"{NUL}", "{SOH}"}
Public Function TestReplace(ByVal p_Message As String) As String
Dim i As Integer
For i = 0 To ((chrArray.Length) - 1)
If p_Message.Contains(chrArray(i).ToString) Then
p_Message = p_Message.Replace(chrArray(i), strArray(i))
End If
Next
Return p_Message
End Function
到目前为止,这是我发现处理这些消息的最快方法。我已经尝试了各种其他方法来解决这个问题,比如将传入的字符串转换为字符数组并进行比较以及尝试遍历字符串而不是chrArray。
所以我的问题是:我可以加快速度吗?我错过了什么?
答案 0 :(得分:1)
您可以通过减少一些查找来挤出更快的速度。以此为例:
If p_Message.Contains(chrArray(i).ToString) Then
.Contains
方法是O(n)。在最坏的情况下,你将遍历整个字符串中的所有字符而不查找任何字符,因此您希望对数组中的每个字符至少遍历一次,因此其O(nm)其中n是n的长度你的字符串和m是你要替换的字符数。
执行以下操作可能会有更好的表现(我的VB-fu生锈了,尚未经过测试;)):
Private Function WriteToCharList(s as String, dest as List(Of Char))
for each c as Char in s
dest.Add(c)
Next
End Function
Public Function TestReplace(ByVal p_Message As String) As String
Dim chars as new List(Of Char)(p_Message.Length)
For each c as Char in p_Message
Select Case c
Case Chr(0): WriteToCharList("{NUL}", chars)
Case Chr(1): WriteToCharList("{SOH}", chars)
Case Else: chars.Add(c);
End Select
Next
Return New String(chars)
End Function
这将最多遍历p_Message
中的字符两次(一次用于遍历,一次在字符串构造函数复制char数组时),使此函数为O(n)。
答案 1 :(得分:0)
StringBuilder
提供了.NET中最快的Replace
()函数。
答案 2 :(得分:0)
这里有几点一般性说明:
.IndexOf()
或.Contains()
搜索来改进搜索功能,因为您只需查找单个字符。至少你可以用这种方式修改你的最终方法:
Public Function TestReplace(ByVal p_Message As String) As String
Static chrArray() As Char = {ChrW(0), ChrW(1)}
Static strArray() As String = {"{NUL}", "{SOH}"}
Dim rdr As New StringReader(p_Message)
Dim result As New StringWriter()
Dim i As Integer
While (i = rdr.Read()) <> -1
Dim c As Char = ChrW(i)
Dim index As Integer = Array.IndexOf(chrArray, c)
If index >= 0 Then result.Write(strArray(index)) Else result.Write(c)
End While
Return result.ToString()
End Function
请注意,您的基准测试将在很大程度上取决于您投射的字符串的类型,因此请确保您使用最具代表性的样本(并且它应该是一个大小合适的样本)。
答案 3 :(得分:0)
看看这个example。它有一些比较这两种方法的基准统计数据。
答案 4 :(得分:0)
这也应该更快:
Private Shared strList As New Dictionary(Of Char, String)
Shared Sub New()
strList.Add(Chr(0), "{NUL}")
strList.Add(Chr(1), "{SOH}")
End Sub
Public Function TestReplace(ByVal p_Message As String) As String
For Each c As Char In strList.Keys
If p_Message.IndexOf(c) <> -1 Then
p_Message = p_Message.Replace(c, strList(c))
End If
Next
Return p_Message
End Function