2011-01-13 36 views
13

Me gustaría dividir una cadena con delimitadores pero mantener los delimitadores en el resultado.Dividir una cadena con delimitadores pero mantener los delimitadores en el resultado en C#

¿Cómo puedo hacer esto en C#?

+4

Por "a | b", ¿quiere "a |" +" b "o" a "+" | b "o" a | "+" | b "o alguna otra cosa? En resumen: ¿a qué segmento pertenece un delimitador? –

+0

Mantenga los delimitadores en el resultado de qué? ¿Desea el delimitador como parte de cada cadena que se dividió? Tu pregunta es bastante vaga –

+0

Oye, me gustaría eliminar una cadena de una lista de caracteres y el resultado de las cadenas también contendrá los delimitadores. Como una sugerencia de veggerby a continuación es algo que me gustaría lograr. Primero lo probaré \ – olidev

Respuesta

17

Si desea que el delimitador para ser su "propia división", puede utilizar Regex.Split por ejemplo:

string input = "plum-pear"; 
string pattern = "(-)"; 

string[] substrings = Regex.Split(input, pattern); // Split on hyphens 
foreach (string match in substrings) 
{ 
    Console.WriteLine("'{0}'", match); 
} 
// The method writes the following to the console: 
// 'plum' 
// '-' 
// 'pear' 
+0

Hola. Gracias. Esto es lo que yo quería. Lo probaré primero. Gracias. Pero, ¿hay alguna forma mejor en lugar de usar Regex? – olidev

+0

Hola, porque mis patrones son, por ejemplo: char [] chars = new char [] {'A', 'B', 'C'}. ¿Sería posible utilizar Split from Regex para mi matriz de caracteres en lugar del patrón de cadena? Gracias de antemano – olidev

+0

hola, ¿y si mi patrón contiene los 4 operadores: +, -, * y/¿Cómo se ve? Gracias – olidev

2

Yo diría que la forma más fácil de lograr esto (excepto para el argumento Hans Kesting crió) es dividir la cadena de la manera habitual, luego iterar sobre la matriz y agregar el delimitador a cada elemento, excepto el último.

+2

Esto solo funciona si tienes 1 delimitador. Si quiero dividir en espacios * y * líneas nuevas, gané ' No sé qué agregar. – thomas88wp

0

que quería hacer una cadena de varias líneas como este, pero necesita para mantener la línea rompe así que hice esta

string x = 
@"line 1 {0} 
line 2 {1} 
"; 

foreach(var line in string.Format(x, "one", "two") 
    .Split("\n") 
    .Select(x => x.Contains('\r') ? x + '\n' : x) 
    .AsEnumerable() 
) { 
    Console.Write(line); 
} 

rendimientos

line 1 one 
line 2 two 
0

me encontré con el mismo problema pero con múltiples delimitadores. Aquí está mi solución:

public static string[] SplitLeft(this string @this, char[] delimiters, int count) 
    { 
     var splits = new List<string>(); 
     int next = -1; 
     while (splits.Count + 1 < count && (next = @this.IndexOfAny(delimiters, next + 1)) >= 0) 
     { 
      splits.Add(@this.Substring(0, next)); 
      @this = new string(@this.Skip(next).ToArray()); 
     } 
     splits.Add(@this); 
     return splits.ToArray(); 
    } 

muestra con la separación de los nombres de variables CamelCase:

var variableSplit = variableName.SplitLeft(
    Enumerable.Range('A', 26).Select(i => (char)i).ToArray()); 
3

Esta versión no utiliza LINQ o expresiones regulares y así es probable que sea relativamente eficiente. Creo que podría ser más fácil de usar que Regex porque no tienes que preocuparte por escapar de los delimitadores especiales. Devuelve IList<string> que es más eficiente que siempre convertir a una matriz. Es un método de extensión, que es conveniente. Puede pasar los delimitadores como una matriz o como múltiples parámetros.

/// <summary> 
/// Splits the given string into a list of substrings, while outputting the splitting 
/// delimiters (each in its own string) as well. It's just like String.Split() except 
/// the delimiters are preserved. No empty strings are output.</summary> 
/// <param name="s">String to parse. Can be null or empty.</param> 
/// <param name="delimiters">The delimiting characters. Can be an empty array.</param> 
/// <returns></returns> 
public static IList<string> SplitAndKeepDelimiters(this string s, params char[] delimiters) 
{ 
    var parts = new List<string>(); 
    if (!string.IsNullOrEmpty(s)) 
    { 
     int iFirst = 0; 
     do 
     { 
      int iLast = s.IndexOfAny(delimiters, iFirst); 
      if (iLast >= 0) 
      { 
       if (iLast > iFirst) 
        parts.Add(s.Substring(iFirst, iLast - iFirst)); //part before the delimiter 
       parts.Add(new string(s[iLast], 1));//the delimiter 
       iFirst = iLast + 1; 
       continue; 
      } 

      //No delimiters were found, but at least one character remains. Add the rest and stop. 
      parts.Add(s.Substring(iFirst, s.Length - iFirst)); 
      break; 

     } while (iFirst < s.Length); 
    } 

    return parts; 
} 

Algunas pruebas unitarias:

text = "[a link|http://www.google.com]"; 
result = text.SplitAndKeepDelimiters('[', '|', ']'); 
Assert.IsTrue(result.Count == 5); 
Assert.AreEqual(result[0], "["); 
Assert.AreEqual(result[1], "a link"); 
Assert.AreEqual(result[2], "|"); 
Assert.AreEqual(result[3], "http://www.google.com"); 
Assert.AreEqual(result[4], "]"); 
+0

Esta es una buena solución. ¿Qué tal si mi delimitador es una cadena? ¿Puede proporcionar una implementación de eso también? – nishantvodoo

0

Para evitar añadiendo carácter nueva línea intente esto:

string[] substrings = Regex.Split(input,@"(?<=[-])"); 
Cuestiones relacionadas