4

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

有人在“全名”字段中键入了一个字符串,我需要将其分解为: Title Firstname Middle Surname Suffix

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

一个完美的例子是:

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

但是,他们可以:

约翰和玛丽·史密斯夫妇

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

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

4

1 回答 1

6

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

其中一些假设如下:

  1. 提供给函数的名称中没有标点符号(例如,带有句点的 Jr.)。
  2. 必须有名字和姓氏,但标题、中间名和后缀是可选的。
  3. 正如问题中所述,唯一的连接运算符是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 == "&";
    }
}
于 2012-10-17T01:58:28.437 回答