Oto moje rozwiązanie. Moim celem nie było dostarczenie najprostszego rozwiązania, ale takiego, które może przyjmować różnorodne (czasem dziwne) formaty nazw i generować najlepsze przypuszczenia na początku i na końcu nazwiska (lub w przypadku osób mononimicznych) na pojedynczy inicjał.
Próbowałem również napisać to w sposób, który jest względnie międzynarodowy, z wyrażeń regularnych unicode, chociaż nie mam żadnego doświadczenia w generowaniu inicjałów dla wielu zagranicznych nazw (np. Chińskich), choć powinno to być najmniej wygenerować coś użytecznego do reprezentowania osoby, poniżej dwóch znaków. Na przykład, podanie nazwy w języku koreańskim, jak "행운 의 복숭아", przyniesie 행복, jak można się było spodziewać (chociaż być może nie jest to właściwy sposób w koreańskiej kulturze).
/// <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();
}
Wygląda na to, że nie działa z francuską wersją typu èè ... Spróbuj z "Stéphane Test" " Bez tego problemu, działa dobrze nawet z - caracter^_- – Danh
Musiałbyś zmodyfikować" zestaw ", który ustawiłem tylko do pracy ze standardowym amerykańskim alfabetem z 52 literami. – Nevyn
W przypadku inicjałów z kropkami, Michael J. Jordan, można zaktualizować wyrażenie tak, aby zawierało znak "\.". Coś podobnego do tego "(\ b [a [z-Z]) [a-zA-Z] * \. *?" – cecilphillip