【问题标题】:Split name into fields?将名称拆分为字段?
【发布时间】:2012-10-07 04:31:14
【问题描述】:

C# 中是否有一个惊人的 RegEx 或方法可以为我实现这一目标?

有人在“全名”字段中输入了一个字符串,我需要将其分解为: 标题 名 中间 姓 后缀

但用户可以输入“John Smith”,因此需要将 John 输入 First Name,将 Smith 输入 Surname。一个人可以键入 Mr John Smith(我有一个已知标题和后缀的列表),所以如果第一个字符串是标题,它会进入 Title 字段。

一个完美的例子是:

小约翰·坎贝尔·史密斯先生

但是,他们可以:

约翰和玛丽·史密斯夫妇

所以标题是先生和夫人,名字是约翰和玛丽,姓是史密斯(他们可以使用“And”或“&”作为连接符)

我猜这对于正则表达式来说太复杂了,但我希望有人可能有一个想法?

【问题讨论】:

  • 我投票赞成“使用单独的字段”。
  • "Smith Jr" 很可能是名字和姓氏(有 2 个字母的姓氏)所以使用单独的字段来确保,像 @AlinMirceaCosma 建议的那样似乎更合乎逻辑。
  • 我们存储为单独的字段。问题是,客户有一个现有的 VB6 应用程序,它按照我描述的方式执行......并希望将其复制到新应用程序中。
  • 只需将您的姓名存储为单个 varchar/字符串。为什么要分手?

标签: c# regex


【解决方案1】:

好的,这是一个我认为可以为您完成工作的程序。您当然可能需要进行一些修改,因为我根据您的问题做出了一些假设,但这肯定会让您朝着正确的方向开始。

其中一些假设如下:

  1. 提供给函数的名称中没有标点符号(例如,带有句点的 Jr.)。
  2. 必须有名字和姓氏,但标题、中间名和后缀是可选的。
  3. 正如问题中所述,only 连接运算符是 and&
  4. 姓名采用这种格式{titles} {first name} {middle name} {last name} {suffix}

我给它起了很多不同的名字,但肯定有更多的可能性,我没有花超过 30 分钟的时间,所以 它没有经过全面测试

class Program
{
    static List<string> _titles = new List<string> { "Mr", "Mrs", "Miss" };
    static List<string> _suffixes = new List<string> { "Jr", "Sr" };

    static void Main(string[] args)
    {
        var nameCombinations = new List<string>
        {
            "Mr and Mrs John and Mary Sue Smith Jr",
            "Mr and Mrs John and Mary Smith Jr",
            "Mr and Mrs John and Mary Sue Smith",
            "Mr and Mrs John and Mary Smith",
            "Mr and Mrs John Smith Jr",
            "Mr and Mrs John Smith",
            "John Smith",
            "John and Mary Smith",
            "John and Mary Smith Jr",
            "Mr John Campbell Smith Jr",
            "Mr John Smith",
            "Mr John Smith Jr",
        };

        foreach (var name in nameCombinations)
        {
            Console.WriteLine(name);

            var breakdown = InterperetName(name);

            Console.WriteLine("    Title(s):       {0}", string.Join(", ", breakdown.Item1));
            Console.WriteLine("    First Name(s):  {0}", string.Join(", ", breakdown.Item2));
            Console.WriteLine("    Middle Name:    {0}", breakdown.Item3);
            Console.WriteLine("    Last Name:      {0}", breakdown.Item4);
            Console.WriteLine("    Suffix:         {0}", breakdown.Item5);

            Console.WriteLine();
        }

        Console.ReadKey();
    }

    static Tuple<List<string>, List<string>, string, string, string> InterperetName(string name)
    {
        var segments = name.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);

        List<string> titles = new List<string>(),
            firstNames = new List<string>();
        string middleName = null, lastName = null, suffix = null;
        int segment = 0;

        for (int i = 0; i < segments.Length; i++)
        {
            var s = segments[i];

            switch (segment)
            {
                case 0:
                    if (_titles.Contains(s))
                    {
                        titles.Add(s);
                        if (segments[i + 1].IsJoiner())
                        {
                            i++;
                            continue;
                        }

                        segment++;
                    }
                    else
                    {
                        segment++;
                        goto case 1;
                    }

                    break;
                case 1:
                    firstNames.Add(s);
                    if (segments[i + 1].IsJoiner())
                    {
                        i++;
                        continue;
                    }

                    segment++;

                    break;
                case 2:
                    if ((i + 1) == segments.Length)
                    {
                        segment++;
                        goto case 3;
                    }
                    else if ((i + 2) == segments.Length && _suffixes.Contains(segments[i + 1]))
                    {
                        segment++;
                        goto case 3;
                    }

                    middleName = s;
                    segment++;

                    break;
                case 3:
                    lastName = s;
                    segment++;

                    break;
                case 4:
                    if (_suffixes.Contains(s))
                    {
                        suffix = s;
                    }

                    segment++;

                    break;
            }
        }

        return new Tuple<List<string>, List<string>, string, string, string>(titles, firstNames, middleName, lastName, suffix);
    }
}

internal static class Extensions
{
    internal static bool IsJoiner(this string s)
    {
        var val = s.ToLower().Trim();
        return val == "and" || val == "&";
    }
}

【讨论】:

  • 效果非常好。它实际上遵循了我们正在走向的模式,但我们失败了。你的完美!谢谢 BigM
  • @Craig,太好了!很高兴能为您提供帮助!
  • 你在这个答案中投入的时间应该得到更多的支持
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-10-26
  • 2020-12-21
  • 1970-01-01
  • 2016-07-25
  • 1970-01-01
  • 2012-12-19
  • 1970-01-01
相关资源
最近更新 更多