2012-09-04 10 views
12

Ho un StringBuilder nome stb_Swap_Tabu utilizzato per memorizzare i nomi del Corso, Sto usando il seguente metodo per trovare un corso:più veloce metodo di ricerca in StringBuilder

stb_Swap_Tabu.ToString.Contains("CourseName") 

nel mio caso, la prestazione è la questione più importante. C'è un modo più veloce?

+1

Se avete bisogno di usare un 'StringBuilder' allora avrete probabilmente bisogno di chiamare' ToString' ogni volta che si desidera ricerca, che non è una grande idea per quanto riguarda le prestazioni. 'StringBuilder' è usato per * costruire stringhe *; presumibilmente se stai costruendo delle stringhe allora hai già le parti costituenti; perché non cerchi direttamente all'interno di quelle parti costitutive? – LukeH

+4

'StringBuilder' è probabilmente il tipo di dati meno adatto per memorizzare un elenco di nomi ricercabili. Perché non usare invece un 'Elenco ' e usare il metodo 'Contains' di' List'? – Rotem

+9

Avete un esempio di cosa sia effettivamente questa stringa? Si dice che memorizza "Nomi dei corsi" - indipendentemente dal fatto che il "Corso" in realtà significhi "Corsi", i "Nomi" suggeriscono più di un nome - quindi presumibilmente questa è una stringa delimitata in qualche modo. In tal caso, passare a 'Lista ' o 'HashSet ' dei nomi * individuali * avrebbe molto senso –

risposta

21

StringBuilder non era realmente inteso per tutti gli scopi di stringa. Se hai davvero bisogno di cercarne uno, devi scrivere il tuo metodo.

Esistono diversi algoritmi di ricerca delle stringhe adatti a casi diversi.

Quanto segue è una semplice implementazione dell'algoritmo Knuth-Morris-Pratt che interessa solo le partite ordinali (nessuna piegatura del caso, nessuna collazione legata alla cultura, solo un semplice punto di codice per codepoint match). Presenta un overhead iniziale Θ(m) in cui m corrisponde alla lunghezza della parola ricercata, quindi trova in Θ(n) dove n è la distanza dalla parola cercata o la lunghezza dell'intero generatore di stringhe se non è presente. Questo è il semplice confronto char-by-char che è Θ((n-m+1) m) (dove la notazione O() descrive i limiti superiori, Θ() descrive entrambi i limiti superiore e inferiore).

Tutto ciò detto, sembra che la creazione di un elenco potrebbe essere un approccio migliore all'attività in corso.

public static class StringBuilderSearching 
{ 
    public static bool Contains(this StringBuilder haystack, string needle) 
    { 
    return haystack.IndexOf(needle) != -1; 
    } 
    public static int IndexOf(this StringBuilder haystack, string needle) 
    { 
    if(haystack == null || needle == null) 
     throw new ArgumentNullException(); 
    if(needle.Length == 0) 
     return 0;//empty strings are everywhere! 
    if(needle.Length == 1)//can't beat just spinning through for it 
    { 
     char c = needle[0]; 
     for(int idx = 0; idx != haystack.Length; ++idx) 
     if(haystack[idx] == c) 
      return idx; 
     return -1; 
    } 
    int m = 0; 
    int i = 0; 
    int[] T = KMPTable(needle); 
    while(m + i < haystack.Length) 
    { 
     if(needle[i] == haystack[m + i]) 
     { 
     if(i == needle.Length - 1) 
      return m == needle.Length ? -1 : m;//match -1 = failure to find conventional in .NET 
     ++i; 
     } 
     else 
     { 
     m = m + i - T[i]; 
     i = T[i] > -1 ? T[i] : 0; 
     } 
    } 
    return -1; 
    }  
    private static int[] KMPTable(string sought) 
    { 
    int[] table = new int[sought.Length]; 
    int pos = 2; 
    int cnd = 0; 
    table[0] = -1; 
    table[1] = 0; 
    while(pos < table.Length) 
     if(sought[pos - 1] == sought[cnd]) 
     table[pos++] = ++cnd; 
     else if(cnd > 0) 
     cnd = table[cnd]; 
     else 
     table[pos++] = 0; 
    return table; 
    } 
} 
+1

Esattamente come @JonHanna menzionato, ho una buona ragione per avere un costruttore ecco perché il titolo della mia domanda è: ** Il metodo di ricerca più veloce in StringBuilder * *. Come risultato del mio test, la risposta fornita da @JonHanna dopo alcune modifiche è stata del 28% migliore rispetto all'utilizzo di 'Conatins'. proverò a creare codice astratto e condividerlo qui. – Alaa

+7

Non ha senso che StringBuilder abbia una funzione 'Sostituisci' che deve necessariamente cercare la stringa e persino prendere indici di inizio e fine, ma non fornisce una funzione' indexOf'. Perché siamo andati a rifare ciò che è già stato fatto? – Slight

+0

Questo codice non funziona per me con il pagliaio "abcde" e l'ago "cd", restituisce false. –

0

So che questa è una vecchia questione ma è venuto nei miei risultati di ricerca quando stavo cercando di creare una soluzione per il mio progetto in cui ho pensato che avevo bisogno di cercare uno StringBuilder ma poi ho ho capito potuto solo cerca il valore che stavo usando per inizializzare il generatore di stringhe. Quindi la mia situazione non può essere uguali ai suoi, ma anche se mi piacerebbe condividere:

Private Function valueFormatter(ByVal value As String) As String 
     ' This will correct any formatting to make the value valid for a CSV format 
     ' 
     ' 1) Any value that as a , in it then it must be wrapped in a " i.e. Hello,World -> "Hello,World" 
     ' 2) In order to escape a " in the value add a " i.e. Hello"World -> Hello""World 
     ' 3) if the value has a " in it then it must also be wrapped in a " i.e. "Hello World" -> ""Hello World"" -> """Hello World""" 
     ' 
     ' VB NOTATAION 
     ' " -> """" 
     ' "" -> """""" 

     If value.Contains(",") Or value.Contains("""") Then 
      Dim sb As New StringBuilder(value) 
      If value.Contains("""") Then sb.Replace("""", """""") 
      sb.Insert(0, """").Append("""") 
      Return sb.ToString 
     Else 
      Return value 
     End If 
    End Function 
Problemi correlati