2011-09-01 17 views
109

C'è un modo migliore per sostituire le stringhe?Sostituisci più caratteri in una stringa

Sono sorpreso che Sostituisci non includa un array di caratteri o un array di stringhe. Immagino di poter scrivere la mia estensione, ma ero curioso di sapere se esiste un modo migliore di fare ciò che segue? Si noti che l'ultima sostituzione è una stringa e non un carattere.

myString.Replace(';', '\n').Replace(',', '\n').Replace('\r', '\n').Replace('\t', '\n').Replace(' ', '\n').Replace("\n\n", "\n"); 

Grazie.

risposta

141

È possibile utilizzare un'espressione regolare di sostituzione.

s/[;,\t\r ]|[\n]{2}/\n/g 
  • s/ all'inizio significa una ricerca
  • I caratteri tra [ e ] sono i caratteri per la ricerca per la (in qualsiasi ordine)
  • Il secondo / delimita il testo di ricerca-e la sostituire il testo

In inglese, questo si legge:

"Cerca ; o , o \t o \r o (spazio) o esattamente due sequenziale \n e sostituirlo con \n"

In C#, è possibile effettuare le seguenti operazioni: (dopo l'importazione System.Text.RegularExpressions)

Regex pattern = new Regex("[;,\t\r ]|[\n]{2}"); 
pattern.Replace(myString, "\n"); 
+1

'\ t' e' \ R' sono inclusi in '\ s'. Quindi la tua regex è equivalente a '[;, \ s]'. – NullUserException

+2

E '\ s' è in realtà equivalente a' [\ f \ n \ r \ t \ v] 'quindi stai includendo alcune cose che non erano nella domanda originale. Addizionalmente, la domanda originale chiede 'Sostituisci (" \ n \ n "," \ n ")' che la tua espressione regolare non gestisce. – NullUserException

+0

Non sono sicuro del perché un RegEx mi sia sfuggito di mente ... grazie. – zgirod

0

Usa RegEx.Replace, qualcosa di simile:

string input = "This is text with far too much " + 
       "whitespace."; 
    string pattern = "[;,]"; 
    string replacement = "\n"; 
    Regex rgx = new Regex(pattern); 

Ecco più informazioni MSDN documentation for RegEx.Replace

85

Se vi sentite particolarmente intelligente e non si desidera utilizzare Regex:

char[] separators = new char[]{' ',';',',','\r','\t','\n'}; 

string s = "this;is,\ra\t\n\n\ntest"; 
string[] temp = s.Split(separators, StringSplitOptions.RemoveEmptyEntries); 
s = String.Join("\n", temp); 

Si potrebbe avvolgere questo in un metodo di estensione con poco sforzo pure.

Edit: O semplicemente attendere 2 minuti e finirò per scriverlo comunque :)

public static class ExtensionMethods 
{ 
    public static string Replace(this string s, char[] separators, string newVal) 
    { 
     string[] temp; 

     temp = s.Split(separators, StringSplitOptions.RemoveEmptyEntries); 
     return String.Join(newVal, temp); 
    } 
} 

E voilà ...

char[] separators = new char[]{' ',';',',','\r','\t','\n'}; 
string s = "this;is,\ra\t\n\n\ntest"; 

s = s.Replace(separators, "\n"); 
+2

+1, e spero che non ti dispiaccia, ma ho usato una versione leggermente modificata del tuo metodo su un mio post di blog. http://learncsharp.org/how-to-properly-and-safely-access-a-database-with-ado-net/ –

41

È possibile utilizzare la funzione di aggregazione di Linq:

string s = "the\nquick\tbrown\rdog,jumped;over the lazy fox."; 
char[] chars = new char[] { ' ', ';', ',', '\r', '\t', '\n' }; 
string snew = chars.Aggregate(s, (c1, c2) => c1.Replace(c2, '\n')); 

Ecco il metodo di estensione:

public static string ReplaceAll(this string seed, char[] chars, char replacementCharacter) 
{ 
    return chars.Aggregate(seed, (str, cItem) => str.Replace(cItem, replacementCharacter)); 
} 
13

Questa è la via più breve:

myString = Regex.Replace(myString, @"[;,\t\r ]|[\n]{2}", "\n"); 
+1

Questo liner aiuta anche quando ne hai bisogno negli inizializzatori. –

5

Ohhh, l'orrore delle prestazioni! La risposta è un po 'obsoleta, ma comunque ...

public static class StringUtils 
{ 
    #region Private members 

    [ThreadStatic] 
    private static StringBuilder m_ReplaceSB; 

    private static StringBuilder GetReplaceSB(int capacity) 
    { 
     var result = m_ReplaceSB; 

     if (null == result) 
     { 
      result = new StringBuilder(capacity); 
      m_ReplaceSB = result; 
     } 
     else 
     { 
      result.Clear(); 
      result.EnsureCapacity(capacity); 
     } 

     return result; 
    } 


    public static string ReplaceAny(this string s, char replaceWith, params char[] chars) 
    { 
     if (null == chars) 
      return s; 

     if (null == s) 
      return null; 

     StringBuilder sb = null; 

     for (int i = 0, count = s.Length; i < count; i++) 
     { 
      var temp = s[i]; 
      var replace = false; 

      for (int j = 0, cc = chars.Length; j < cc; j++) 
       if (temp == chars[j]) 
       { 
        if (null == sb) 
        { 
         sb = GetReplaceSB(count); 
         if (i > 0) 
          sb.Append(s, 0, i); 
        } 

        replace = true; 
        break; 
       } 

      if (replace) 
       sb.Append(replaceWith); 
      else 
       if (null != sb) 
        sb.Append(temp); 
     } 

     return null == sb ? s : sb.ToString(); 
    } 
} 
0

Prestazioni: questa probabilmente potrebbe non essere la soluzione migliore ma funziona.

var str = "filename:with&bad$separators.txt"; 
char[] charArray = new char[] { '#', '%', '&', '{', '}', '\\', '<', '>', '*', '?', '/', ' ', '$', '!', '\'', '"', ':', '@' }; 
foreach (var singleChar in charArray) 
{ 
    str = str.Replace(singleChar, '_'); 
} 
2

Le stringhe sono array di char solo immutabili

Hai solo bisogno di rendere mutevole:

  • sia utilizzando StringBuilder
  • andare nel mondo unsafe e giocare con i puntatori (pericoloso però)

e prova ad eseguire l'iterazione attraverso la serie di caratteri il minor numero di volte.

Esempio con StringBuilder

public static void MultiReplace(this StringBuilder builder, char[] toReplace, char replacement) 
    { 
     HashSet<char> set = new HashSet<char>(toReplace); 
     for (int i = 0; i < builder.Length; ++i) 
     { 
      var currentCharacter = builder[i]; 
      if (set.Contains(currentCharacter)) 
      { 
       builder[i] = replacement; 
      } 
     } 
    } 

Poi basta usarlo così:

var builder = new StringBuilder("my bad,url&slugs"); 
builder.MultiReplace(new []{' ', '&', ','}, '-'); 
var result = builder.ToString(); 
Problemi correlati