簡體   English   中英

正則表達式從 Name 中提取首字母

[英]Regex to extract initials from Name

eg. if the Name is: John Deer
the Initials should be: JD

我可以使用子字符串對 Initials 字段執行此檢查,但想知道是否可以為其編寫正則表達式? 編寫正則表達式是否比使用字符串方法更好?

這是我的解決方案。 我的目標不是提供最簡單的解決方案,而是提供一種可以采用多種(有時很奇怪)名稱格式的解決方案,並在名字和姓氏的首字母(或匿名人的情況下)一個首字母時生成最佳猜測。

我還嘗試以一種相對國際友好的方式編寫它,使用 unicode 正則表達式,盡管我沒有任何為多種外國名稱(例如中文)生成首字母的經驗,盡管它至少應該生成一些可用的東西代表人,在兩個字符以下。 例如,給它一個像“행운의 복숭아”這樣的韓語名字會產生 행복 ,正如你可能預期的那樣(盡管在韓國文化中這可能不是正確的做法)。

/// <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();
}

就個人而言,我更喜歡這個正則表達式

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

這需要處理首字母和空格刪除(那是末尾的“?”)。

您唯一需要擔心的是頭銜和標點符號,例如 Jr. 或 Sr.,或 Mrs.... 等。有些人確實在他們的全名中包含了這些

這是我的方法:

public static string GetInitials(string names) {
    // Extract the first character out of each block of non-whitespace
    // exept name suffixes, e.g. Jr., III. The number of initials is not limited.
    return Regex.Replace(names, @"(?i)(?:^|\s|-)+([^\s-])[^\s-]*(?:(?:\s+)(?:the\s+)?(?:jr|sr|II|2nd|III|3rd|IV|4th)\.?$)?", "$1").ToUpper();
}

處理過的案例:

// Mason Zhwiti                               -> MZ
// mason zhwiti                               -> MZ
// Mason G Zhwiti                             -> MGZ
// Mason G. Zhwiti                            -> MGZ
// John Queue Public                          -> JQP
// John-Queue Public                          -> JQP
// John Q. Public, Jr.                        -> JQP
// John Q Public Jr.                          -> JQP
// John Q Public Jr                           -> JQP
// John Q Public Jraroslav                    -> JQPJ
// Thurston Howell III                        -> TH
// Thurston Howell, III                       -> TH
// Thurston Howell the III                    -> TH
// Malcolm X                                  -> MX
// A Ron                                      -> AR
// A A Ron                                    -> AAR
// Madonna                                    -> M
// Chris O'Donnell                            -> CO
// Chris O' Donnell                           -> COD
// Malcolm McDowell                           -> MM
// Éric Ígor                                  -> ÉÍ
// 행운의 복숭아                               -> 행복

未處理案例:

// James Henry George Michael III the second  -> JHGMIts
// Robert "Rocky" Balboa, Sr.                 -> R"B
// 1Bobby 2Tables                             -> 12 (is it a real name?)

這個怎么樣?

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

這是一個強調保持簡單的替代方案:

    /// <summary>
    /// Get 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();
    }

如果提供的名稱不符合預期,該怎么辦是一個問題。 就我個人而言,我認為它應該只返回每個非空白文本塊的第一個字符。 例如:

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

有些人會爭論更復雜/更復雜的技術(例如更好地處理最后一個技術),但 IMO 這確實是一個數據清理問題。

試試這個

(^| )([^ ])([^ ])*','\2')

或者這個

 public static string ToInitials(this string str)
    {
      return Regex.Replace(str, @"^(?'b'\w)\w*,\s*(?'a'\w)\w*$|^(?'a'\w)\w*\s*(?'b'\w)\w*$", "${a}${b}", RegexOptions.Singleline)
    }

http://www.kewney.com/posts/software-development/using-regular-expressions-to-get-initials-from-a-string-in-c-sharp

[az]+[az]+\\b這將讓你凈每個名字的前兩個字母...

其中名稱 = 'Greg Henry' = 'GH' 或 'James Smith' 'J S'

然后你可以在 ' ' 上拆分並在 '' 上加入

這甚至適用於像這樣的名字

'詹姆斯·亨利·喬治·邁克爾' = 'JHG M'

'詹姆斯·亨利·喬治·邁克爾三世第二' = 'JHGM III'

如果您想避免拆分,請使用[az]+[az]+\\b ?

但是然后像Jon Michael Jr. The 3rd這樣的名字Jon Michael Jr. The 3rd將是 = JMJr.T3 ,因為上面的選項允許你得到“The”、“the”和“3rd”,如果你想要的話..

如果你真的想要花哨,你可以使用(\\b[a-zA-Z])[a-zA-Z]* ? 只匹配名稱的部分,然后用前者替換。

這個怎么樣:

        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();

這允許可選的中間名,並適用於多種大寫,如上所示。

我的解決方案如下(C#正則表達式方言)

^\s*(?>(?<First>\w)\w*).*?((?<Last>\w)\w*)?\s*$

將在命名組FirstLast匹配第一個單詞的第一個字母和Last一個單詞的第一個較晚的字母,樂於忽略可能介於兩者之間的所有單詞並且不關心是否有尾隨或前導空格

不需要替換,匹配發生在一行中,您可以像這樣按名稱提取訪問匹配組的字母

var displayName = "Nick 'Goose' Bradshaw";
var initialsRule = new Regex(@"^\s*(?>(?<First>\w)\w*).*?((?<Last>\w)\w*)?\s*$");
var matches = initialsRule.Match(displayName);
var initials = $"{matches.Groups["First"].Value}{matches.Groups["Last"].Value}";
//initials: "NB"

kotlin 中最簡單的版本

val initials: String = if (str.size > 1) str[0][0].toString() + str[1][0].toString() else str[0][0].toString()

是的,使用正則表達式。 您可以使用 Regex.Match 和 Regex.Match.Groups 方法來查找匹配項,然后提取您需要的匹配值 - 在本例中為首字母。 查找和提取值將同時發生。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM