C # dividió la cadena pero mantiene dividir caracteres / separadores

Estoy dividiendo una cadena por tres caracteres diferentes, pero quiero que la salida incluya los caracteres con los que me divido. ¿Hay alguna manera fácil de hacer esto?

Si los caracteres de división fueran,, . y , Probaría:

 string[] parts = Regex.Split(originalString, @"(?<=[.,;])") 

(?<=PATTERN) es una apariencia positiva detrás de PATTERN . Debe coincidir en cualquier lugar donde el texto anterior se ajuste a PATTERN por lo que debería haber una coincidencia (y una división) después de cada aparición de cualquiera de los caracteres.

Partiendo de la respuesta de BFree, tenía el mismo objective, pero quería dividirme en una matriz de caracteres similar al método original de Split, y también tengo múltiples divisiones por cadena:

 public static IEnumerable SplitAndKeep(this string s, char[] delims) { int start = 0, index; while ((index = s.IndexOfAny(delims, start)) != -1) { if(index-start > 0) yield return s.Substring(start, index - start); yield return s.Substring(index, 1); start = index + 1; } if (start < s.Length) { yield return s.Substring(start); } } 

Solo en caso de que alguien quiera esta respuesta también …

En lugar de string[] parts = Regex.Split(originalString, @"(?<=[.,;])") string[] parts = Regex.Split(originalString, @"(?=yourmatch)") usar string[] parts = Regex.Split(originalString, @"(?=yourmatch)") donde tu yourmatch es cualquiera que sea tu separador.

Suponiendo que la cuerda original fuera

777- gato

777 - perro

777 - ratón

777 - rata

777 - lobo

Regex.Split(originalString, @"(?=777)") volvería

777 - gato

777 - perro

y así

Esto parece funcionar, pero no se ha probado mucho.

 public static string[] SplitAndKeepSeparators(string value, char[] separators, StringSplitOptions splitOptions) { List splitValues = new List(); int itemStart = 0; for (int pos = 0; pos < value.Length; pos++) { for (int sepIndex = 0; sepIndex < separators.Length; sepIndex++) { if (separators[sepIndex] == value[pos]) { // add the section of string before the separator // (unless its empty and we are discarding empty sections) if (itemStart != pos || splitOptions == StringSplitOptions.None) { splitValues.Add(value.Substring(itemStart, pos - itemStart)); } itemStart = pos + 1; // add the separator splitValues.Add(separators[sepIndex].ToString()); break; } } } // add anything after the final separator // (unless its empty and we are discarding empty sections) if (itemStart != value.Length || splitOptions == StringSplitOptions.None) { splitValues.Add(value.Substring(itemStart, value.Length - itemStart)); } return splitValues.ToArray(); } 
 result = originalString.Split(separator); for(int i = 0; i < result.Length - 1; i++) result[i] += separator; 

( EDITAR - esta es una mala respuesta - Leí mal su pregunta y no vi que estaba dividido por varios personajes).

(EDITAR: una versión correcta de LINQ es incómoda, ya que el separador no debe concatenarse en la cadena final en la matriz dividida).

Recientemente escribí un método de extensión para esto:

 public static class StringExtensions { public static IEnumerable SplitAndKeep(this string s, string seperator) { string[] obj = s.Split(new string[] { seperator }, StringSplitOptions.None); for (int i = 0; i < obj.Length; i++) { string result = i == obj.Length - 1 ? obj[i] : obj[i] + seperator; yield return result; } } } 

Iterar a través de la cadena carácter por carácter (que es lo que hace la expresión regular de todos modos. Cuando encuentre un divisor, entonces escinde una subcadena.

pseudo código

 int hold, counter; List afterSplit; string toSplit for(hold = 0, counter = 0; counter < toSplit.Length; counter++) { if(toSplit[counter] = /*split charaters*/) { afterSplit.Add(toSplit.Substring(hold, counter)); hold = counter; } } 

Eso es una especie de C # pero no realmente. Obviamente, elija los nombres de función apropiados. Además, creo que podría haber un error "por-1" allí.

Pero eso hará lo que estás preguntando.

¡Muchas respuestas a esto! Uno que golpeé para dividirlo por varias cuerdas (la respuesta original solo sirve para caracteres, es decir, longitud de 1). Esto no ha sido probado completamente.

 public static IEnumerable SplitAndKeep(string s, params string[] delims) { var rows = new List() { s }; foreach (string delim in delims)//delimiter counter { for (int i = 0; i < rows.Count; i++)//row counter { int index = rows[i].IndexOf(delim); if (index > -1 && rows[i].Length > index + 1) { string leftPart = rows[i].Substring(0, index + delim.Length); string rightPart = rows[i].Substring(index + delim.Length); rows[i] = leftPart; rows.Insert(i + 1, rightPart); } } } return rows; } 

Regex.Split parece que podría hacer lo que quieras, tal vez.

 using System.Collections.Generic; using System.Text.RegularExpressions; namespace ConsoleApplication9 { class Program { static void Main(string[] args) { string input = @"This;is:a.test"; char sep0 = ';', sep1 = ':', sep2 = '.'; string pattern = string.Format("[{0}{1}{2}]|[^{0}{1}{2}]+", sep0, sep1, sep2); Regex regex = new Regex(pattern); MatchCollection matches = regex.Matches(input); List parts=new List(); foreach (Match match in matches) { parts.Add(match.ToString()); } } } } 

Código Java:

 public static class String_Ext { public static string[] SplitOnGroups(this string str, string pattern) { var matches = Regex.Matches(str, pattern); var partsList = new List(); for (var i = 0; i < matches.Count; i++) { var groups = matches[i].Groups; for (var j = 0; j < groups.Count; j++) { var group = groups[j]; partsList.Add(group.Value); } } return partsList.ToArray(); } } var parts = "abcde \tfgh\tikj\r\nlmno".SplitOnGroups(@"\s+|\S+"); for (var i = 0; i < parts.Length; i++) Print(i + "|" + Translate(parts[i]) + "|"); 

Salida:

 0|abcde| 1| \t| 2|fgh| 3|\t| 4|ikj| 5|\r\n| 6|lmno|