2010-08-25 20 views
5

Tengo el hilo por debajo delcadena Splitter en .NET

P,MV,A1ZWR,MAV#(X,,), PV,MOV#(X,12,33),LO 

necesito la salida como

P 

MV 

A1ZWR 

MAV#(X,,) 

PV 

MOV#(X,12,33) 

LO 

Como se puede distinguir que se puede hacer fácilmente mediante la división por "" pero el problema viene

cuando es de tipo MAV # (X ,,) o MOV # (X, 12,33).

Por favor, ayudar a

Respuesta

4

Dado que no había tal solución usando solo LINQ y estaba interesado en cómo se vería, se me ocurrió esto. Pero no recomendaría usarlo en el código de producción. En realidad, esperaba que fuera más agradable, pero como los parenthenidos anidados deben manejarse, tuve que introducir variables de estado mutables.

string data = "P,MV,A1ZWR,MAV#(X,,), PV,MOV#(X,12,33),LO"; 

int depth = 0; 
int group = 0; 

var result = data 
    .GroupBy(x => { 
     if (x == '(') depth++; 
     if (x == ')') depth--; 
     if (x == ',' && depth == 0) group++; 
     return group; }) 
    .Select(x => new String(x.ToArray()).Trim(' ', ',')) 
0

utiliza un carácter separador que no va a ser parte de sus entradas.

P~MV~A1ZWR~MAV#(X,,)~ PV~MOV#(X,12,33)~LO 

O incluso un personaje invisible (0x00?)

+0

Hay un problema, ya que incluso puede venir como P!, MV ~, # MOB (x, 9,8) –

2

La mejor opción es escribir un programa de análisis de los datos. Busque una biblioteca de análisis CSV, probablemente pueda modificar una para admitir #(...) en lugar de "..." sin demasiada dificultad.

0

Si este es un archivo que está rellenando, use un delimitador que no sea un problema, como el | por ejemplo. Si se trata de un archivo que está escaneando y analizando, probablemente pueda usar expresiones regulares para extraer los datos que necesita.

Si no es así, es posible que tenga que dividir las cadenas y mirar las cubetas mientras busca problemas y realiza las fusiones y divisiones necesarias.

8

Puede usar una expresión regular para hacer coincidir los valores entre los separadores, y especificar que todo dentro de las parantheses es parte del valor. Ejemplo:

string data = "P,MV,A1ZWR,MAV#(X,,), PV,MOV#(X,12,33),LO"; 

foreach (Match m in Regex.Matches(data, @"\s*((\(.*?\)|[^,])*)(,|$)")) { 
    Console.WriteLine(m.Groups[1].Value); 
} 

de salida:

P 
MV 
A1ZWR 
MAV#(X,,) 
PV 
MOV#(X,12,33) 
LO 
+3

Cabe mencionar sin embargo que esto se romperá tan pronto como se anidan paréntesis Además, como una cuestión de diseño, es un inconveniente de su solución que falle silenciosamente omitiendo/faltando entradas (en lugar de tirar). – Timwi

+0

@Timwi: Buen punto, la solución, por supuesto, tiene limitaciones, ya que no es un analizador completo. Mientras tengas una cuerda bien formada que no sea más complicada que el ejemplo, funciona bien. – Guffa

1

¿Qué hay de bucle y la detección de caracteres de marcas tales como ( y ):

string[] test = "P,MV,A1ZWR,MAV#(X,,), PV,MOV#(X,12,33),LO".Split(','); 

bool insideElement = false; 
string insideElementResult = ""; 
List<string> result = new List<string>(); 
foreach (string s in test) 
{ 
    //Determine context: 
    if (s.IndexOf("(") > -1) 
     insideElement = true; 

    //Determine where to add my nice string 
    if (!insideElement) 
     result.Add(s); 
    else 
     insideElementResult += s; 

    //Determine if contact has ended: 
    if (s.IndexOf(")") > -1) 
    { 
     insideElement = false; 
     result.Add(insideElementResult); 
     insideElementResult = null; 
    } 
    else if (insideElement) 
    { 
     insideElementResult += ","; 
    } 

} 

resultados en:

[0] "P" string 
    [1] "MV" string 
    [2] "A1ZWR" string 
    [3] "MAV#(X,,)" string 
    [4] " PV" string 
    [5] "MOV#(X,12,33)" string 
    [6] "LO" string 

Por supuesto, no tan elegante como expresiones regulares, y se romperá en el paréntesis interior, pero bueno, funciona;)

4
string input = "P,MV,A1ZWR,MAV#(X,,), PV,MOV#(X,12,33),LO"; 
IList<string> parts = new List<string>(); 
int paranthesisCount = 0; 
int lastSplitIndex = 0; 
for (int i = 0; i < input.Length; i++) 
{ 
    if (input[i] == '(') 
    { 
     paranthesisCount++; 
     continue; 
    } 
    if (input[i] == ')') 
    { 
     paranthesisCount--; 
     continue; 
    } 
    if (input[i] == ',' && paranthesisCount == 0) 
    { 
     parts.Add(input.Substring(lastSplitIndex, i - lastSplitIndex)); 
     lastSplitIndex = i + 1; 
    } 
} 
if (input.Length - lastSplitIndex > 0) 
{ 
    parts.Add(input.Substring(lastSplitIndex, input.Length - lastSplitIndex)); 
} 
+2

+1 para cuidar paréntesis anidados. Sin embargo, debe tenerse en cuenta que esto fallará en silencio si falta un paréntesis cerrado. – Timwi

1

Para comprender la cadena también es un analizador puede ser de ayuda. El analizador más simple es recursivo. De esa manera usted puede estar seguro de que

  1. todos los paréntesis son bien
  2. no hay divisiones equivocadas occour
  3. todas las fichas son correctas (que puede ser de ayuda, pero depende de la aplicación)

Un buen analizador que tiene la comprobación de errores es como tener un xsd para su idioma específico.

He hecho un analizador con ANTLR.Compruébalo si te ayuda. Puede ser una exageración en el problema. Solo piensa en ello.

0

Ésta es la función será sacar todas las fichas, asegúrese de que no hay comas dobles entre fichas, y asegúrese de que todos los paréntesis están cerrados. Es un poco largo

IEnumerable<string> Tokenise(string input) 
{ 
    const char tokenlimiter = ','; 
    const char funcstart = '#'; 
    const char funcend = ')'; 
    StringBuilder token = new StringBuilder(5); 
    bool gotfunc = false; 
    bool gotone = false; 
    int pos = 0; 
    int opened = 0; 
    foreach(char c in input) 
    { 
     if (c == funcstart) 
     { 
      gotfunc = true; 
      opened++; 
     } 
     if(c == funcend) 
     { 
      gotfunc = false; 
      opened--; 
     } 
     if(!gotfunc && c == tokenlimiter) 
     { 
      gotone = true; 
      if(token.Length == 0) 
      { 
       throw new ArgumentException("Blank instruction at " + pos, input); 
      } 
      yield return token.ToString(); 
     } 
     if(gotone) 
     { 
      token = new StringBuilder(5); 
      gotone = false; 
     } 
     else 
     { 
      token.Append(c);  
     } 
     if(pos == input.Length - 1) 
     { 
      if (!gotfunc && opened == 0 && c != tokenlimiter) 
      { 
       yield return token.ToString(); 
      } 
      else if (gotfunc || opened != 0) 
      { 
       throw new ArgumentException("Broken function", input); 
      } 
      else 
      { 
       throw new ArgumentException("Blank instruction at " + pos, input); 
      } 
     } 
     pos++; 
    } 

} 
0
private static void CreateListString(string s) 
{ 
string[] splits = s.Split(new char[] { ',' }); 
List<string> strs = new List<string>(); 
bool isLimiterSeen = false; 
StringBuilder str = null; 
for (int i = 0; i < splits.Length; i++) 
{ 
if (splits[i].Contains("#(")) 
{ 
isLimiterSeen = true; 
str = new StringBuilder(); 
} 
if (!isLimiterSeen) 
strs.Add(splits[i]); 
else 
{ 
str = str.Append("," + splits[i]); 
if (splits[i].EndsWith(")")) 
{ 
if (str.ToString().StartsWith(",")) 
strs.Add(str.ToString().Substring(1)); 
else 
strs.Add(str.ToString()); 
isLimiterSeen = false; 
str = null; 
} 
} 
} 
} 
Cuestiones relacionadas