Here is my solution. My goal was not to provide the simplest solution, but one that could take different (sometimes weird) name formats and generate the best guess for the first and last name (or in the case of anonymous people) with one initial.
I also tried to write it in a way that is relatively international, with unicode regular expressions, although I have no experience generating initials for many kinds of foreign names (e.g. Chinese), although it should at least generate something suitable for representing a person , under two characters. For example, serving it in Korean like βνμ΄ μ 볡μμβ will give you ν볡 as you might expect (although this may not be the right way to do this in Korean culture).
/// <summary> /// Given a person 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, eg "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 /// AA 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(); }