2011-09-01 33 views
109

¿Existe alguna forma mejor de reemplazar cadenas?Reemplazar varios caracteres en una cadena

Me sorprende que Replace no tome una matriz de caracteres o una matriz de cadenas. Supongo que podría escribir mi propia extensión, pero tenía curiosidad de saber si existe una mejor manera de hacer lo siguiente. Observe que el último reemplazo es una cadena, no un personaje.

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

Gracias.

Respuesta

141

Puede usar una expresión regular de reemplazo.

s/[;,\t\r ]|[\n]{2}/\n/g 
  • s/ en la base significa una búsqueda
  • Los caracteres entre [ y ] son los caracteres que se busca para (en cualquier orden)
  • El segundo / delimita el texto de búsqueda para y la reemplazar texto

En inglés, esto dice:

"búsqueda de ; o , o \t o \r o (espacio) o exactamente dos secuencial \n y reemplazarlo con \n"

En C#, se podría hacer lo siguiente: (después de importar System.Text.RegularExpressions)

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

'\ t' y' \ R' están incluidos en '\ s'. Entonces tu expresión regular es equivalente a '[;, \ s]'. – NullUserException

+2

Y '\ s' es en realidad equivalente a' [\ f \ n \ r \ t \ v] 'por lo que está incluyendo algunas cosas que no estaban en la pregunta original. Además, la pregunta original pide 'Reemplazar (" \ n \ n "," \ n ")' que su expresión regular no maneja. – NullUserException

+0

No estoy seguro de por qué un RegEx escapó de mi mente ... gracias. – zgirod

0

uso RegEx.Replace, algo como esto:

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

Aquí hay más información sobre este MSDN documentation for RegEx.Replace

85

Si se siente particularmente inteligente y no desea utilizar expresiones regulares:

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); 

Usted podría terminar con esto en un método de extensión con poco esfuerzo también.

Editar: O sólo tiene que esperar 2 minutos y voy a terminar de escribir de todos modos :)

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); 
    } 
} 

y listo ...

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

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

+1, y espero que no te importe, pero utilicé una versión ligeramente modificada de tu método en una publicación de blog mía. http://learncsharp.org/how-to-properly-and-safely-access-a-database-with-ado-net/ –

41

Se puede usar la función agregada de 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')); 

Aquí está el método de extensión:

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

Este es el camino más corto:

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

Este delineador también ayuda cuando lo necesita en inicializadores. –

5

Ohhh, el horror rendimiento! La respuesta está un poco desactualizada, pero aún así ...

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

Performance-Wise esto probablemente no sea la mejor solución, pero funciona.

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

Las cadenas son arrays de char simplemente inmutables

Sólo se necesita para que sea mutable:

  • ya sea mediante el uso de StringBuilder
  • vaya en el mundo unsafe y jugar con los punteros (peligroso sin embargo)

y trate de iterar a través de la matriz de caracteres la menor cantidad de veces.

Ejemplo 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; 
      } 
     } 
    } 

A continuación, sólo tiene que utilizar de esa manera:

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