Zeichenersetzung in Strings in VB.NET
-
29-09-2019 - |
Frage
Wie schnell kann ich Zeichen in einer Zeichenfolge ersetzen?
So ist der Hintergrund dieser Frage ist diese: Wir haben ein paar Anwendungen, die miteinander und mit Kunden Anwendungen über Sockets kommunizieren. Diese Socket-Nachrichten enthalten nicht druckbare Zeichen (zB chr (0)), die mit einer vorbestimmten Zeichenfolge ersetzt bekommen muß (zB „{Nul}“}, da die Socket-Nachrichten in einer Log-Datei gespeichert werden. Auf einer Seite zur Kenntnis, nicht jede Protokollmeldung müssen Zeichen haben ersetzt.
Nun begann ich auf dieses kleine Abenteuer Lesen von dieser MSDN Link , die ich von einem anderen Beitrag von dieser Seite gefunden.
Die aktuelle Methode verwendeten wir ... am Anfang des Tages ... wurde mit String für alle möglichen Alternativen zu prüfen, wie ...
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
Jetzt als Blog-Post weist darauf hin verlassen Stringbuilder und mit string.replace tut Ausbeute schnellere Ergebnisse. (Eigentlich String Verwendung war die langsamste Methode, dies den ganzen Tag lang zu tun.)
p_Message = p_Message.Replace(Chr(0), "{NUL}")
p_Message = p_Message.Replace(Chr(1), "{SOH}")
Das Wissen, dass nicht jede Nachricht durch diesen Prozess gehen müsste ich dachte, es Zeit sparen würde nicht diese Nachrichten verarbeiten müssen, die weggelassen werden könnte. Ich suchte zuerst die Zeichenfolge so mit regulären Ausdrücken und dann bestimmt, wenn sie verarbeitet werden müssen oder nicht. Das war ungefähr die gleiche wie die string.replace verwenden, im Grunde eine Wäsche von Speichern, die Zeit nicht alle die Saiten der Verarbeitung, aber von der Überprüfung sich alle mit regulären Ausdrücken zu verlieren Zeit.
Dann wurde vorgeschlagen, zu versuchen, einige Arrays, dass ihre Indizes mit den alten und den neuen und dem Einsatz abgestimmt, dass die Nachrichten zu verarbeiten. So wäre es so etwas wie dieses ...
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
Das bisher der schnellste Weg, die ich gefunden habe, diese Nachrichten zu verarbeiten. Ich habe verschiedene andere Weise versucht der ebenso wie die Umwandlung der eingehenden Zeichenfolge in ein Zeichenarray über diese gehen und den Vergleich zusammen mit auch eher eine Schleife durch die Zeichenfolge versuchen, als die ChrArray.
Also meine Frage an alle ist: Kann ich diese noch schneller zu machen? Was bin ich?
Lösung
Das könnte Sie der Lage sein, ein wenig mehr Geschwindigkeit zu verdrängen, indem sie einige Lookups reduzieren. Nehmen Sie zum Beispiel dieses:
If p_Message.Contains(chrArray(i).ToString) Then
Die .Contains
Methode ist O (n). Im schlimmsten Fall, Sie gehen alle die Zeichen in der gesamten Zeichenfolge zu durchqueren, ohne etwas zu finden, so dass Sie mindestens einmal für jedes Zeichen in Ihrem Array zu durchqueren erwarten, so dass ihr O (nm), wobei n die Länge Ihr String und m ist die Anzahl der Zeichen Sie ersetzen.
Sie könnte ein wenig bessere Leistung bekommen Sie wie folgt vorgehen (mein VB-fu rostig ist, wurde nicht geprüft;)):
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
Dies wird durchqueren Zeichen in p_Message
höchstens zweimal (einmal für Verfahrweg, einmal, wenn die Zeichenfolge Konstruktor kopiert der char-Array), so dass diese Funktion O (n).
Andere Tipps
Dies sollte auch schneller:
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
StringBuilder
bietet die schnellste Replace
() Funktion in .NET.
Ein paar allgemeine Hinweise hier:
- Sie könnten in der Lage sein, auf die Suchfunktion zu verbessern, indem sie eine einfache
.IndexOf()
oder.Contains()
Suche verwenden, da Sie nur sind für einzelne Zeichen suchen. - Möglicherweise können Sie Ihren Gesamtdurchsatz verbessern, indem das Stringbuilder-Objekts aus Ihrer Funktion direkt Rückkehr und Überlastungen für andere Funktionen bereitstellt, die Stringbuilders als Eingabe oder Aufruf .ToString () irgendwo später im Prozess (Anmerkung akzeptieren: Sie können auch rufen .ToString () auf Objekte, die bereits Strings)
- Sie sollten definitiv in der Lage sein, die Leistung weiter zu verbessern / Durchsatz durch einen String / Textreader weiter oben in der Kette und solange als Strom zu behandeln alles, was die Kette bestand bis halten zu werden.
Am allerwenigsten können Sie Ihre endgültige Methode, um diese Art und Weise ändern:
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
Beachten Sie, dass Ihre Benchmarks stark von der Art der Saiten abhängen Sie sind Werfen es an, so stellen Sie sicher, dass Sie die meisten repräsentative Stichprobe mit (und es sollte eine gute Größe Probe sein) möglich.
Haben Sie einen Blick auf diese Beispiel . Es hat einige Benchmark-Statistiken Vergleich der beiden Methoden.