2010-02-22 8 views
6

el formato de cadena es siempre así: "Nombre = ABC; Apellido = XZY; Nombre de usuario = Usuario1; Contraseña = 1234".cómo subservir desde una cadena usando C#?

Necesito el único valor de nombre de usuario (que es 'Usuario1' en este caso). Quiero lograr esto en una línea mínima de código usando el método de subcadena (u otra cosa).

¿Ayuda?

+0

Cuando un problema tiene respuestas muy definitivos como este siempre es divertido para mí ver cómo muchas soluciones diferentes a la comunidad así lo dispone. –

+0

Una cosa a tener en cuenta: la cadena de entrada tiene un campo llamado "Nombre del usuario ** n **". A continuación, solicita el campo "Usuario ** N ** ame". Tenga cuidado con la carcasa al analizar cadenas. Hay formas de lidiar con esto, por supuesto. –

Respuesta

4

Este método funcionará incluso si los pares de valores se dan en un orden diferente. Se divide en el punto y coma, encuentra el elemento con "Nombre de usuario" y luego devuelve lo que está después del signo igual.

string theString = "FirstName=ABC;LastName=XZY;Username=User1;Password=1234"; 
string username = theString.Split(";").Where(s => s.Split("=")[0].Equals("Username")).ToArray()[0].Split("=")[1]; 
+0

@ Aaron: Lamento preguntar, es la sintaxis oke. Estoy recibiendo un error cerca de .ToArray [0] .. ?? – Jango

+0

@ user144842: ¡Ha detectado un error en mi ejemplo! Se supone que hay paréntesis después de ToArray. He actualizado mi respuesta. – Aaron

+0

Eso sería la mitad de VB y la mitad de C# ... probablemente todo fuera de su cabeza. –

12

Parece que una cadena delimitada, por lo que esto funcionaría:

string result = myString.Split(';')[2].Split('=')[1]; 

Sin embargo, si alguien cambia el orden par de valores, esto va a romper.

Hay mejores formas de hacerlo, que no se romperán si el orden cambia, el número de parámetros es diferente, etc., como la Expresión regular como la publicada por Michael, o las consultas de Linq publicadas por varias personas.

+0

me gano :( –

+3

Aprecio que estuvieras intentando hacerlo lo más corto posible, pero creo que tenemos el ganador del código más feo que he visto recientemente. (Sin intención de ofender!) – brian

+0

No lo haría No es el código más feo que haya existido, pero el usuario obtuvo lo que quería ... –

4

El menor número de líneas de código no siempre es la mejor métrica, pero puede hacer lo que necesita con Regex.

+1

Qué extraño, esta es probablemente una de las primeras veces que he visto una expresión regular sugerida y es una respuesta válida. : p – Tanzelax

+0

¿No has oído hablar? Algunas personas, cuando se enfrentan con un problema, piensan "Lo sé, usaré expresiones regulares". Ahora ellos tienen dos problemas. Jamie Zawinski – Oded

+0

@Tanzelax: ¿Regex se convierte en el nuevo JQuery? – brian

1
 string t = "FirstName=ABC;LastName=XZY;Username=User1;Password=1234"; 
     string name = t.Split(';')[2].Split('=')[1]; 
7

Aquí es una solución alternativa (no muy diferente de los demás, pero que creo que es más sencillo) que funcionará sin importar el orden.

var input = "FirstName=ABC;LastName=XZY;Username=User1;Password=1234"; 

Assert.AreEqual("User1", input 
    .Split(';') 
    .Select(item => item.Split('=')) 
    .Where(pair => pair[0].Equals("Username")) 
    .Single()[1]); 
+0

Se produce un error cuando no hay un "Nombre de usuario" en la cadena. –

+0

Si no puede haber un nombre de usuario, puede agregar '.Select (pair => pair [1])' before '.Single()' y cambiar '.Single()' a '.SingleOrDefault()'. Entonces obtienes nulo si no hay un nombre de usuario. –

15

Para completar, aquí está la forma Regex de hacerlo. Esto también funcionará si la orden cambia.

// using System.Text.RegularExpressions; 

string test1 = "FirstName=ABC;LastName=XZY;Username=User1;Password=1234"; 
string test2 = "FirstName=ABC;LastName=XZY;Password=1234;Username=User1"; 
string test3 = "FirstName=ABC;LastName=XZY;Password=1234"; 

string regexPattern = @"(?<=Username=)[^;\n]*"; 
var userName1 = Regex.Match(test1, regexPattern).Value; // User1 
var userName2 = Regex.Match(test2, regexPattern).Value; // User1 
var userName3 = Regex.Match(test3, regexPattern).Value; // string.Empty 

// Compiling can speed up the Regex, at the expense of longer initial Initialization 
// Use when this is called often, but measure. 

Regex compiledRx = new Regex(regexPattern,RegexOptions.Compiled); 
var userNameCompiled1 = compiledRx.Match(test1).Value; // User1 
var userNameCompiled2 = compiledRx.Match(test2).Value; // User1 
var userNameCompiled3 = compiledRx.Match(test3).Value; // string.Empty 
+1

Este es realmente un buen lugar para aplicar expresiones regulares. Buen material. –

3

Si bien las respuestas son divididas 'bien' si nada cambia, probablemente es mejor usar una función porque:

  • Hace que sus intenciones claras.
  • Es más fácil de documentar.
  • Es más fácil de modificar si ocurre lo inevitable.
  • Funciona independientemente del orden.

(Incluso si usted acaba de poner la división de una línea en la función o por lo menos dejar un comentario a la división!.)


static String GetUsername(String value) 
{ 
    String result = ""; 
    String token = "Username="; 

    int index = value.IndexOf(token) + token.Length; 
    while (value[index] != ';') 
    { 
     result += value[index++]; 
     if (index > value.Length - 1) 
      break; 
    } 

    return result; 
} 
+0

Me gusta la sugerencia de encapsular esta "lógica", pero seamos malvados: su muestra no terminó en un ';'. Ahora imagine que la parte "Nombre de usuario =" está al final, ¿qué pasaría con su solución? –

+3

@Benjamin - Aunque no es difícil de manejar ese caso; Creo que todas las soluciones presentadas adolecen de alguna deficiencia. Por ejemplo, ¿qué pasa si hay dos nombres de usuario en la cadena? ¿Qué pasaría? Esta solución siempre elegiría la primera. En cualquier caso, creo que este problema trivial ha sido llevado a un extremo. –

+0

De acuerdo, y +1 para eso :) –

3

No es tan simple como usar dividida, sin embargo:

string input = "FirstName=ABC;LastName=XZY;Username=User1;Password=1234"; 
string username = Regex.Match(input, "Username=(?<username>.*?)(;|$)").Groups["username"].Value; 

En este caso, los grupos pueden estar en cualquier orden.

Y, si te gusta ser creativo:

var answers = from tuple in input.Split(';') 
       where tuple.StartsWith("Username=") 
       select tuple.Split('=')[1]; 

username = answers.Count() > 0 ? answers.First() : string.Empty; 

Uno podría decir que la última pieza tiene mejores semántica.

EDITAR: Actualice la última pieza para tratar cadenas de entrada que no tienen la tupla requerida.

+0

Fallaría si la cadena fuente es 'FirstName = ABC; Nombre de usuario = Usuario1; Apellido = XZY; Contraseña = 1234'. Use '' 'para una búsqueda perezosa:' Nombre de usuario = (? . *?); ' –

+0

@Naeem Sarfraz: Gracias, tienes razón. Maldita cosa codiciosa. Además, corregí el caso en el que el nombre de usuario es el último par de la cadena. Y ahora el REGEX es muy complejo ... –

1

Este no es el más corto ... pero probablemente uno de los más rápidos.

string value = "FirstName=ABC;LastName=XZY;Username=User1;Password=1234"; 
int offset = value.IndexOf("Username=") + 9; 
if (offset < 9) 
    throw new Exception("Username= not found in string"); 
int len = value.IndexOf(';', offset) - offset; 
if (len < 0) 
    len = value.Length - offset; 
string find = value.Substring(offset, len); 

... la if (len < 0) es para es el nombre de usuario se encuentra al final de la cadena y no termina con un punto y coma. Si desea ignorar caso puede reemplazar la línea int offset con esto ...

int offset = value.ToUpperInvariant().IndexOf("USERNAME=") + 9; 
+0

Sé que el "número mágico" podría reemplazarse moviendo "Nombre de usuario =" a una variable como token y usando token.Length. –

+0

No dude en quejarse sobre "Excepción". No me apetecía nada mejor como ejemplo. –

Cuestiones relacionadas