Question

Combien de temps puis-je remplacer les caractères dans une chaîne?

Ainsi, le fond sur cette question est la suivante: Nous avons deux ou trois applications qui communiquent entre eux et avec les applications de ses clients par le biais de prises. Ces messages de socket contiennent des caractères non-imprimables (par exemple chr (0)) qui ont besoin de se remplacer par une chaîne prédéterminée (par exemple « {Nul} »}, parce que les messages de socket sont conservés dans un fichier journal. Sur une note latérale, non chaque message de journal devra avoir remplacé les caractères.

Maintenant, je commencé sur cette petite lecture d'aventure ce lien MSDN que j'ai trouvé à partir d'un autre poste de ce site.

La méthode actuelle, nous avons utilisé ... au début de la journée ... utilisait StringBuilder pour vérifier tous les remplacements possibles tels que ...

    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

Maintenant, comme les points de billet de blog en laissant StringBuilder à l'aide et String.replace ne donne des résultats plus rapides. (En fait, en utilisant StringBuilder est la méthode la plus lente de le faire toute la journée.)

    p_Message = p_Message.Replace(Chr(0), "{NUL}")
    p_Message = p_Message.Replace(Chr(1), "{SOH}")

Sachant que pas chaque message aurait besoin de passer par ce processus, je pensais que ce serait de gagner du temps de ne pas avoir à traiter ces messages qui pourraient être laissés de côté. Donc, en utilisant des expressions régulières j'ai cherché la chaîne, puis déterminé si elle devait être traitée ou non. Il était environ le même que l'utilisation du String.replace, essentiellement un lavage de sauver le temps de ne pas traiter toutes les chaînes, mais de perdre du temps de les vérifier toutes les expressions régulières.

Ensuite, il a été suggéré d'essayer d'utiliser des tableaux qui correspondent à leurs index avec l'ancien et le nouveau et l'utiliser pour traiter les messages. Donc, ce serait quelque chose comme ça ...

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

a été jusqu'ici le plus rapide que j'ai trouvé pour traiter ces messages. J'ai essayé d'autres façons d'aller à ce sujet ainsi que la conversion de la chaîne entrant dans un tableau de caractères et de comparer avec en essayant de boucle à travers la chaîne plutôt que le chrArray.

Alors ma question à tous est: Puis-je faire cela plus rapidement encore? Qu'est-ce que je manque?

Était-ce utile?

La solution

Vous pourriez être en mesure de faire sortir un peu plus de vitesse en réduisant certaines recherches. Prenons par exemple ceci:

    If p_Message.Contains(chrArray(i).ToString) Then

La méthode de .Contains est O (n). Dans le pire des cas, vous allez parcourir tous les caractères de la chaîne entière sans trouver quoi que ce soit, si vous vous attendez à traverser au moins une fois pour chaque caractère dans votre tableau, de sorte que son O (nm) où n est la longueur votre chaîne et m est le nombre de caractères que vous remplacez.

Vous pouvez obtenir un peu de meilleures performances à faire ce qui suit (ma VB-fu est rouillé, n'a pas été testé;)):

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

Ceci va traverser caractère en p_Message au plus deux fois (une fois pour le déplacement, une fois lorsque les copies du constructeur de la chaîne de tableau de caractères), ce qui rend cette fonction O (n).

Autres conseils

Cela devrait également être plus rapide:

    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 offre la plus rapide fonction Replace () dans .NET.

Quelques notes générales ici:

  1. Vous pourriez être en mesure d'améliorer la fonction de recherche en utilisant un ou .IndexOf() recherche .Contains() plaine, puisque vous êtes à la recherche que pour un seul caractère.
  2. Vous pourriez être en mesure d'améliorer votre débit total en retournant l'objet StringBuilder de votre fonction directement et en fournissant des surcharges pour d'autres fonctions qui acceptent stringbuilders en entrée ou en appelant .toString () quelque part plus tard dans le processus (note: Vous pouvez également appel .ToString () sur les objets qui sont déjà des chaînes)
  3. Vous devez certainement être en mesure d'améliorer les performances / débit plus loin en utilisant un StringReader / TextReader plus haut dans la chaîne et continuer à tout traiter comme cours d'eau qui continue à recevoir laissé passer la chaîne.

À tout le moins, vous pouvez modifier votre méthode finale de cette façon:

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

Notez que vos points de repère dépendra en grande partie du type de chaînes que vous jetez à elle, alors assurez-vous que vous utilisez le plus échantillon représentatif (et il devrait être un bon échantillon de taille) possible.

Jetez un oeil à cette exemple . Il a des statistiques de référence comparant les deux méthodes.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top