2009-04-07 27 views
5

C#, .NET 3.5Analizando una cadena en C#; ¿hay una manera más limpia?

Esto me huele feo, pero no se me ocurre otra manera.

Dada una cadena con el formato "Joe Smith (jsmith)" (sin comillas), me gustaría analizar solo la cadena 'jsmith' entre paréntesis. Yo he llegado con esto:

private static string DecipherUserName(string user) 
{ 
    if(!user.Contains("(")) 
     return user; 

    int start = user.IndexOf("("); 

    return user.Substring(start).Replace("(", string.Empty).Replace(")", string.Empty); 
} 

Aparte de mi (des) aversión saludable para expresiones regulares, hay una manera más fácil de analizar fuera de la subcadena?

Editar: Para aclarar, la cadena a analizar será siempre de: "Joe Smith (jsmith)" (sans comillas).

Respuesta

9

No debería ser necesario reemplazar la primera desde que Sólo puede añadir 1 a la "(" posición.

private static string DecipherUserName (string user) {   
    int start = user.IndexOf("("); 
    if (start == -1) 
     return user; 
    return user.Substring (start+1).Replace(")", string.Empty); 
} 
+0

Nota: acepté el refactor de Pax sobre la solución RegEx, ya que creo que a largo plazo, será más fácil de mantener hasta que tenga más conocimientos sobre RegEx. Eso, y una prueba rápida de 1000 nombres tuvo la solución RegEx en .1165195 ms frente a la solución String en .0077423 ms. –

+0

Para una coincidencia de texto simple como esta, las RE son generalmente más lentas (aunque pueden compilarse una vez para obtener velocidad extra en un bucle). Su ventaja real viene con su expresividad para casos más complejos (por ejemplo, permitir y eliminar espacios dentro del paréntesis). Merece la pena aprender, así que sigan así. – paxdiablo

2

Dado que la función IndexOf volverá -1 cuando no existe el valor, usted podría hacer las cosas un poco diferentes ...

private static string DecipherUserName(string user) 
{   
    int start = user.IndexOf("("); 

    if (start > -1) 
    { 
     return user.Substring(start).Replace("(", string.Empty).Replace(")", string.Empty); 
    } 
    else 
    { 
     return user; 
    } 
} 
+0

Olvidé que IndexOf devolverá -1 cuando el valor no exista. ¡Gracias! –

20

expresiones regulares son tan útiles que se ahorrará un montón de dolores de cabeza mordiendo la bala y aprendiendo. No todo el shebang, solo lo básico.

Una expresión regular que funcionará es "\ w + \ ((. *) \)" - jsmith estaría en Match.Groups [1].

Una manera fácil de aprender expresiones regulares es encontrar un sitio web que va a dejar que se escribe en una expresión regular y algo de texto y luego escupir los partidos ...

+0

+1 para expresiones regulares, ya que es la herramienta correcta –

+0

No hay un requisito explícito de que el nombre de usuario incluido en el código paren debe seguir un nombre sin espacios. "\ (. * \)" debería ser suficiente. – James

+0

Herramienta correcta pero RE incorrecta: necesita una que maneje el caso de un usuario sin paréntesis. Hazlo y te daré una votación :-) – paxdiablo

5

especie de truco ... ^^

return user.Substring(user.IndexOf('(') + 1).TrimEnd(')'); 

Si user no contiene paréntesis de apertura, IndexOf() devuelve -1, agregamos uno, obtenemos cero, y SubString() devuelve la cadena completa. TrimEnd() no tendrá ningún efecto a menos que el nombre del usuario termine con un paréntesis de cierre.

Si user contiene un paréntesis de apertura, IndexOf() devuelve su índice, que SKIPP del paréntesis de apertura mediante la adición de uno, y extraer el resto de la cadena con Substring(). Finalmente eliminamos el paréntesis de cierre con TrimEnd().

+0

Buen uso de la cadena API. –

+0

Esto no refleja muy bien la intención. –

+0

Primera línea: tipo de truco ... ^^;) –

1

que haría uso de

int start=user.IndexOf('('); 
if (start != -1) { 
    end = user.IndexOf(')', start); 
    return user.Substring(start+1,end-start-1); 
} else 
    return user; 

Pero esto es sólo un cambio cosmético: el uso de caracteres en IndexOf es un poco más rápido, y utilizando el método Subcadena parece expresar más exactamente lo que debe hacerse (y el método es más robusto si tiene varios pares de paréntesis, ...)

dicho esto, Daniel método L 's (usando String.Split) podría ser más simple (pero no se ocupa muy bien con cadenas malformadas y tiene que construir una matriz de cadenas).

En general, le sugiero que supere su aversión a las expresiones regulares, ya que esa situación es exactamente para lo que están destinadas :-) ...

+0

@Martin - Bueno, es una aversión (no) saludable (-_ ^) Tu comentario acerca de que la subcadena es más expresiva es definitivamente cierta. –

5

Si la cadena de usuario siempre tiene el formato "Joe Smith (jsmith)", esto debería funcionar.

private static string DecipherUserName(string user) 
{ 
    string[] names = user.Split(new char[] {'(', ')'}); 
    return names.Length > 2 ? names[1] : user; 
} 

Y si la cadena del usuario siempre es "Joe Smith (jsmith)", esto siempre funcionará.

private static string DecipherUserName(string user) 
{ 
    return "jsmith"; 
} 

La segunda entrada para propósitos de humor solamente.

Cuestiones relacionadas