2012-05-30 22 views
6
eg. if the Name is: John Deer 
the Initials should be: JD 

Puedo utilizar subcadenas para realizar esta comprobación en el campo de iniciales, pero me pregunto si puedo escribir una expresión regular para ello. ¿Y escribir una expresión regular es una mejor idea que hacerlo usando métodos de cuerdas?Regex para extraer iniciales del nombre

Respuesta

13

Personalmente, prefiero esta expresión regular

Regex initials = new Regex(@"(\b[a-zA-Z])[a-zA-Z]* ?"); 
string init = initials.Replace(nameString, "$1"); 
//Init = "JD" 

que se encarga de las iniciales, y la eliminación de espacios en blanco (que es el '?' Al final allí).

Lo único que debe preocuparse son los títulos y la puctuación como Jr. o Sr., o Sra ...., etc. etc.Algunas personas sí incluyen los de sus nombres completos

+0

Parece que no funciona con el caracter francés como é ... Pruebe con "Stéphane Test " Sin ese problema, funciona bien incluso con - caracter^_- – Danh

+0

Tendría que modificar el" conjunto "Solo lo arreglé para que funcione con el alfabeto inglés americano estándar de 52 caracteres. – Nevyn

+0

Para las iniciales con puntos, Michael J. Jordan, puede actualizar la expresión para incluir un "\". Algo como esto "(\ b [a-zA-Z]) [a-zA-Z] * \. *?" – cecilphillip

2

¿Qué tal esto?

var initials = Regex.Replace("John Deer", "[^A-Z]", ""); 
+0

No se olvide de todos esos Scotts, Harrold McDonnald saldrá como HMD – IanNorton

+0

Sólo funcionará si el nombre está en mayúscula ... – Jay

0

Sí, utilice un regex. Puede usar los métodos Regex.Match y Regex.Match.Groups para buscar coincidencias y luego extraer los valores coincidentes que necesita: las iniciales en este caso. Encontrar y extraer valores ocurrirá al mismo tiempo.

0

[a-z]+[a-z]+\b la que le reporte Las dos primeras letras de cada nombre ...

donde name = 'Greg Henry' = 'GH' o 'James Smith' 'JS'

entonces se puede dividir en '' y unirse en ''

Esto funciona incluso en los nombres como

'James Henry George Michael' = 'JHGM'

'James Henry George Michael III el segundo'= 'JHGM III'

Si se quiere evitar la escisión utilizar [a-z]+[a-z]+\b ?

Pero entonces nombres como Jon Michael Jr. The 3rd serán = JMJr.T3 en tanto que la opción anterior le permite obtener 'El', 'the' y '3rd' si quisiera ...

Si realmente deseaba ser elegante, podría usar el (\b[a-zA-Z])[a-zA-Z]* ? para hacer coincidir solo las partes del nombre y luego reemplazarlo con el primero.

0

¿Qué tal esto:

 string name = "John Clark MacDonald"; 
     var parts = name.Split(' '); 
     string initials = ""; 

     foreach (var part in parts) 
     { 
      initials += Regex.Match(part, "[A-Z]"); 
      Console.WriteLine(part + " --> " + Regex.Match(part,"[A-Z]")); 
     } 
     Console.WriteLine("Final initials: " + initials); 
     Console.ReadKey(); 

Esto permite que los segundos nombres opcionales, y trabaja para varias capitalizaciones, como se muestra arriba.

1

Aquí está una alternativa con un énfasis en hacer que sea sencillo:

/// <summary> 
    /// Gets initials from the supplied names string. 
    /// </summary> 
    /// <param name="names">Names separated by whitespace</param> 
    /// <param name="separator">Separator between initials (e.g. "", "." or ". ") </param> 
    /// <returns>Upper case initials (with separators in between)</returns> 
    public static string GetInitials(string names, string separator) 
    { 
     // Extract the first character out of each block of non-whitespace 
     Regex extractInitials = new Regex(@"\s*([^\s])[^\s]*\s*"); 
     return extractInitials.Replace(names, "$1" + separator).ToUpper(); 
    } 

No es una cuestión de qué hacer si los nombres suministrados no son los esperados. Personalmente, creo que debería devolver el primer carácter de cada fragmento de texto que no sea un espacio en blanco. Por ejemplo:

1Steve 2Chambers    => 12 
harold mcDonald    => HM 
David O'Leary     => DO 
David O' Leary     => DOL 
Ronnie "the rocket" O'Sullivan => R"RO 

Habrá aquellos que diría de técnicas más sofisticadas/complejos (por ejemplo, para manejar el último mejor) pero En mi opinión esto es realmente un problema de limpieza de datos.

+0

Se ve muy bien Señor. Encontré una hoja de trucos para Regexes en C# aquí por cierto: http://www.mikesdotnetting.com/article/46/c-regular-expressions-cheat-sheet –

13

Aquí está mi solución. Mi objetivo no era proporcionar la solución más simple, sino una que puede tomar una variedad de formatos de nombres (a veces extraños), y generar la mejor estimación en una inicial de nombre y apellido (o en el caso de personas monónimas) una sola inicial.

También traté de escribirlo de una manera relativamente internacionalmente amigable, con expresiones regulares unicode, aunque no tengo ninguna experiencia en generar iniciales para muchos tipos de nombres extranjeros (por ejemplo, chino), aunque debería hacerlo en Al menos genere algo utilizable para representar a la persona, en menos de dos caracteres. Por ejemplo, al darle un nombre en coreano como "행운 의 will" se obtendrá 행복 como podría haber esperado (aunque tal vez esa no sea la forma correcta de hacerlo en la cultura coreana).

/// <summary> 
/// Given a person's first and last name, we'll make our best guess to extract up to two initials, hopefully 
/// representing their first and last name, skipping any middle initials, Jr/Sr/III suffixes, etc. The letters 
/// will be returned together in ALL CAPS, e.g. "TW". 
/// 
/// The way it parses names for many common styles: 
/// 
/// Mason Zhwiti    -> MZ 
/// mason lowercase zhwiti  -> MZ 
/// Mason G Zhwiti    -> MZ 
/// Mason G. Zhwiti    -> MZ 
/// John Queue Public   -> JP 
/// John Q. Public, Jr.   -> JP 
/// John Q Public Jr.   -> JP 
/// Thurston Howell III   -> TH 
/// Thurston Howell, III  -> TH 
/// Malcolm X     -> MX 
/// A Ron      -> AR 
/// A A Ron      -> AR 
/// Madonna      -> M 
/// Chris O'Donnell    -> CO 
/// Malcolm McDowell   -> MM 
/// Robert "Rocky" Balboa, Sr. -> RB 
/// 1Bobby 2Tables    -> BT 
/// Éric Ígor     -> ÉÍ 
/// 행운의 복숭아     -> 행복 
/// 
/// </summary> 
/// <param name="name">The full name of a person.</param> 
/// <returns>One to two uppercase initials, without punctuation.</returns> 
public static string ExtractInitialsFromName(string name) 
{ 
    // first remove all: punctuation, separator chars, control chars, and numbers (unicode style regexes) 
    string initials = Regex.Replace(name, @"[\p{P}\p{S}\p{C}\p{N}]+", ""); 

    // Replacing all possible whitespace/separator characters (unicode style), with a single, regular ascii space. 
    initials = Regex.Replace(initials, @"\p{Z}+", " "); 

    // Remove all Sr, Jr, I, II, III, IV, V, VI, VII, VIII, IX at the end of names 
    initials = Regex.Replace(initials.Trim(), @"\s+(?:[JS]R|I{1,3}|I[VX]|VI{0,3})$", "", RegexOptions.IgnoreCase); 

    // Extract up to 2 initials from the remaining cleaned name. 
    initials = Regex.Replace(initials, @"^(\p{L})[^\s]*(?:\s+(?:\p{L}+\s+(?=\p{L}))?(?:(\p{L})\p{L}*)?)?$", "$1$2").Trim(); 

    if (initials.Length > 2) 
    { 
     // Worst case scenario, everything failed, just grab the first two letters of what we have left. 
     initials = initials.Substring(0, 2); 
    } 

    return initials.ToUpperInvariant(); 
} 
+0

Mason muy bien hecho. Aunque solo probé contra nombres en inglés, funciona y cubre una variedad de escenarios. – Aggromonster

Cuestiones relacionadas