C# 在C中从全名字符串中分离firstname和lastname#

C# 在C中从全名字符串中分离firstname和lastname#,c#,regex,string,C#,Regex,String,我正在做一个网站迁移,包括从全名中提取firstname和lastname。鉴于这些都是由最终用户创建的,因此存在各种排列(尽管英语和一般不太奇怪)。大多数情况下,我可以将第一个单词作为firstname,最后一个单词作为lastname,但偶尔会出现前缀和后缀的例外情况。在浏览数据并试图了解所有可能的异常时,我意识到这是一个常见的问题,以前至少已经部分解决了很多次 在重新发明轮子之前,是否有人拥有任何适用于它们的正则表达式或有用的代码?性能不是一个考虑因素,因为这是一个一次性实用程序 要处理的

我正在做一个网站迁移,包括从全名中提取firstname和lastname。鉴于这些都是由最终用户创建的,因此存在各种排列(尽管英语和一般不太奇怪)。大多数情况下,我可以将第一个单词作为firstname,最后一个单词作为lastname,但偶尔会出现前缀和后缀的例外情况。在浏览数据并试图了解所有可能的异常时,我意识到这是一个常见的问题,以前至少已经部分解决了很多次

在重新发明轮子之前,是否有人拥有任何适用于它们的正则表达式或有用的代码?性能不是一个考虑因素,因为这是一个一次性实用程序

要处理的典型值:

杰森·布里格斯, J.D.史密斯, 约翰,我的公民, J.斯科特·迈尔斯, 比尔·杰克布森三世, 约翰·米尔斯先生


更新:虽然这是一个常见问题,但典型的解决方案似乎涉及处理大多数情况,并手动清洁其余情况


(鉴于这个问题必须经历的频率,我原本期望在那里找到一个实用库,但是我自己找不到一个谷歌)

如果这是一次性的交易,那么我会强烈地考虑付钱给某个专家来替你做。 他们将有处理结构不良数据集的经验


我与他们没有任何关系,但我提供的服务似乎是为这类事情量身定做的。

这可能是不可能做到的(可靠的)

即使你能为一些名字写下这些,你也会在某个时候得到一个西班牙人,他会写下两个姓氏。或者有些人(忘了是哪个国籍)会写上“姓氏”。或者其他许多情况中的一种


你能做的最好的方法是将两个单词分成名字和姓氏,然后手动检查其余的单词(你自己,或者雇佣一些专业人士).

这是一个不确定的问题(或者我喜欢称之为Oracle问题),无法以可靠的方式解决。这是因为存在着名和姓的名字,例如斯坦利、杰克逊等,但可以尝试一下。你需要编写一个学习程序,给你一组名字和姓氏,它将维护一个这些名字的字典,根据名字的概率映射

现在,传递所有要迁移的值,并使用这些概率,您可以在名字和姓氏之间得到合理的划分。此外,如果某个特定名称变得模棱两可(完全由您来定义模棱两可,但我会将其定义为我获得的所有概率值的底部30%),那么您可以将其标记以供以后查看

希望这有帮助


干杯

我的建议如下:

  • 在空格上拆分名称

  • 检查返回数组的长度。如果为2,则容易拆分。如果更多,下一个

  • 比较前缀的第一个值(即Mr.Mrs.Ms.Dr.)…如果是,请将其删除,否则移动到下一个

  • 比较第一个值的长度。如果只有1个字符,则组合数组中的前2项

  • 它仍然不是万无一失的;然而,它应该解决至少80%的案例


    希望这对您有所帮助。

    如果您只有少数用户(最快的方法是一种混合算法-人工方法。你不想把时间花在构建一个99.99%工作时间的系统上,因为最后5-10%的优化会让你丧命。此外,你也不想把所有的工作都推到一个人身上,因为大多数情况(我猜)都相当简单

    因此,快速构建类似Jamesegers建议的内容,但捕获所有看起来不寻常或不符合预定义转换的情况。然后,只需手动检查这些情况(不应该太多)

    您可以自己查看这些案例,或者通过在Mechanical Turk中设置HITs将其外包给其他用户:

    (假设500个案例的价格为$0.05(高回报),那么您的总成本最多应该是$25)

    我找到了一个非常简单的正则表达式(可能是80%),并添加了一些快乐的C组名称:

    (?(先生、女士、女士、小姐、博士)\?\s+(?)\s+(?)(?((范德冯)s+)\s+(?)


    我以维基的形式发布,所以任何人都可以随意添加他们认为有帮助的东西!

    正如其他人指出的,没有任何解决方案可以在所有情况下都有效。 这样做的一个原因是,有些名字既可以用作名字,也可以用作姓氏

    你可以使用一个名数据库,找出名字的哪一部分是可能的名字。如果你还知道某个名字的人的国家,你可以大大提高准确度


    有关免费的名字数据库,请参见。

    如果您的数据范围是数据库中有多少个名字?大约10K,因此使用处理95%的案例的解决方案进行手动检查仍然是可行的。使用第一个和最后一个字处理大约85%的名称。此外,对于J.D.Smith这样的案例,您可以主要处理J.D.是姓,Smith是姓。我同意这一点,如果你能将数据分解成各种可靠的解析数据集,你可能会发现剩下的“故障案例”小到足以让人操控。James-感谢你的非常实用的想法。鉴于数据通常相当好,我认为这应该可以解决约95%的情况。大约有10000个用户,所以你可能是对的-这是程序员不合理的强迫,他们花5个小时试图解决一半的边缘情况,这需要一个小时一个实习生的“手工”清洗。确切地说;-)我只很清楚我认为你是对的。语言的排列和无结构的性质导致这是一个不确定的问题
    static void CheckSuffix(ref string[] sArrName)
    {
    // Initialize suffixes
    List<string> Suffixes = new List<string>();
    Suffixes.Add("jr");
    Suffixes.Add("sr");
    Suffixes.Add("esq");
    Suffixes.Add("ii");
    Suffixes.Add("iii");
    Suffixes.Add("iv");
    Suffixes.Add("v");
    Suffixes.Add("2nd");
    Suffixes.Add("3rd");
    Suffixes.Add("4th");
    Suffixes.Add("5th");

            int i = 0;
            string suffix = string.Empty;
            foreach (string s in sArrName)
            {
                string[] schk = s.ToLower().Split(new char[] { ' ' });
                foreach (string sverifiy in schk)
                {
                    if (Suffixes.Contains(sverifiy))
                    {
                        suffix = sverifiy;
                        sArrName[i] = sArrName[i].Replace(sverifiy.ToUpper(), string.Empty).Trim();
                    };
                }
                i += 1;
            }
            sArrName[2] = string.Format("{0}{1}", sArrName[2], (!string.IsNullOrEmpty(suffix) ? " " + suffix.ToUpper() + "." : string.Empty));
        }
        public static string[] ExtractFullname(string name)
        {
            string[] sArr = { "", "", ""};
            string[] sName = name.Split(new char[] { ' ', ',', '.' }, StringSplitOptions.RemoveEmptyEntries);
            int chkinitial = -1;
            for (int i = 0; i < sName.Length; i++)
            {
                if (sName[i].Length == 1) chkinitial = i;
            }
    
            switch (sName.Length)
            {
                case 1:
                    sArr[0] = name;
                    break;
                case 2:
                    {
                        int idx = name.IndexOf(',');
                        if (idx != -1 && idx < name.Length) { sArr[0] = sName[1]; sArr[2] = sName[0]; } /* last, first */
                        else
                        {
                            idx = name.IndexOf(' ');
                            if (idx != -1 && idx < name.Length) { sArr[0] = sName[0]; sArr[2] = sName[1]; } /* first last */
                        }
                    }
                    break;
                case 3:
                    if (chkinitial == 1) { sArr[0] = sName[0]; sArr[1] = sName[1]; sArr[2] = sName[2]; } /* first middle last */
                    else if (chkinitial == 2) { sArr[0] = sName[1]; sArr[1] = sName[2]; sArr[2] = sName[0]; } /* last first middle */
                    else if (chkinitial == -1) {
                        int idx = name.IndexOf(',');
                        if (idx != -1)
                        {
                            if (idx == (sName[0].Length + sName[1].Length + 1))
                            {
                                sArr[0] = sName[2]; sArr[2] = string.Format("{0} {1}", sName);
                            }
                            else
                            {
                                sArr[0] = string.Format("{1} {2}", sName); sArr[2] = sName[0];
                            }
                        }
                        else
                        {
                            sArr[0] = name;
                        }
                    }
                    break;
                case 4:
                    if (chkinitial == 1) { sArr[0] = sName[0]; sArr[1] = sName[1]; sArr[2] = string.Format("{2} {3}", sName); } /* first middle last */
                    else if (chkinitial == 2) { sArr[0] = string.Format("{0} {1}", sName); sArr[1] = sName[2]; sArr[2] = sName[3]; } /* last first middle */
                    else if (chkinitial == 3) {
                        int idx = name.IndexOf(',');
                        if (idx != -1)
                        {
                            if (idx == (sName[0].Length + sName[1].Length + 1))
                            {
                                sArr[0] = sName[2]; sArr[1] = sName[3]; sArr[2] = string.Format("{0} {1}", sName);
                            }
                            else
                            {
                                sArr[0] = string.Format("{1} {2}", sName); sArr[1] = sName[3]; sArr[2] = sName[0];
                            }
                        }
                        else
                        {
                            sArr[0] = name;
                        }
                    }
                    else if (chkinitial == -1)
                    {
                        int idx = name.IndexOf(',');
                        if (idx != -1)
                        {
                            if (idx == (sName[0].Length))
                            {
                                sArr[0] = string.Format("{1} {2} {3}", sName); sArr[2] = sName[0];
                            }
                            else if (idx == (sName[0].Length + sName[1].Length + 1))
                            {
                                sArr[0] = string.Format("{2} {3}", sName); sArr[2] = string.Format("{0} {1}", sName);
                            }
                            else if (idx == (sName[0].Length + sName[1].Length + sName[2].Length + 1))
                            {
                                sArr[0] = sName[3]; sArr[2] = string.Format("{0} {1} {2}", sName);
                            }
                            else
                            {
                                sArr[0] = name;
                            }
                        }
                        else
                        {
                            sArr[0] = name;
                        }
                    }
                    break;
                default:
                    /* more than 3 item in array */
                    sArr[0] = name;
                    break;
            }
            CheckSuffix(ref sArr);
            return sArr;
        }