将一个人的名字解析为其组成部分的简单方法?

时间:2020-03-06 14:26:46  来源:igfitidea点击:

我们输入姓名(例如" John W. Smith")时,许多联系人管理程序都会这样做,它会在内部自动将其分解为:

名:约翰
中间名:W。
姓氏:Smith

同样,它计算出"简·史密斯夫人"和"小约翰·道伊博士"这样的东西。同样正确(假设名称中允许使用" prefix"和" suffix"之类的字段)。

我认为这是人们想要做的相当普遍的事情……所以问题是……你会怎么做?为此有一个简单的算法吗?也许是正则表达式?

我正在寻求.NET解决方案,但我并不挑剔。

更新:我很高兴没有一个简单的解决方案可以涵盖所有边际情况和文化……但是,为了争辩,我们需要分块命名(填写表格,例如在税收或者其他政府中)表单是一种情况,无论我们是否喜欢,都必须在固定字段中输入名称),但是我们不必强迫用户在离散字段中输入其名称(较少输入=对于新手用户来说更容易)。

我们可能希望程序在第一个,中间,最后一个等位置"猜测"(尽可能)。如果可以,请查看Microsoft Outlook如何为联系人执行此操作,以便我们键入名称,但是如果我们需要澄清一下,我们可以打开一个额外的小窗口。如果用户想以离散形式输入名称,我会做同样的事情给用户一个窗口,但允许在一个框中输入名称,并做一个涵盖最常用名称的"最佳猜测"。

解决方案

如果我们必须执行此解析,我相信我们会在这里得到很多好的建议。

我的建议是不要执行此解析。

而是,创建输入字段,以便信息已被分离出来。对于标题,名字,中间名首字母,姓氏,后缀等有单独的字段。

对此没有简单的解决方案。名称的构造因文化而异,甚至在英语世界中,前缀和后缀也不一定是名称的一部分。

一种基本的方法是在字符串的开头(例如" Hon。John Doe")寻找尊称,在数字的末尾寻找数字(例如" John Doe IV"," John Doe Jr.")但实际上我们所能做的就是运用启发式方法,并希望获得最好的结果。

查找未处理名称的列表并针对该名称测试算法可能会很有用。我不知道那里有什么预先包装的东西。

我们可以做一些显而易见的事情:将Jr.,II,III等作为后缀,并将Mr.,Mrs.,Dr。等作为前缀并删除它们,然后第一个单词为名字,最后一个单词为最后名称,介于两者之间的都是中间名。除此之外,还没有万无一失的解决方案。

一个很好的例子是David Lee Roth(姓氏:Roth)和Eddie Van Halen(姓氏:Van Halen)。如果安·玛丽·史密斯(Ann Marie Smith)的名字是"安·玛丽"(Ann Marie),则无法将其与安·玛丽的中间名区分开。

我会说从列表中删除称呼,然后按空格分开,将list.first()作为名字,将list.last()作为姓氏,然后将其余部分加一个空格,并将其作为中间名。并在上方显示结果,并让用户对其进行修改!

我同意<B>不这样做。 Rick Van DenBoer这个名字的开头是Van的中间名,但这是姓氏的一部分。

当然,有一个简单的解决方案将字符串按空格分割,计算令牌的数量,如果有2,则将其解释为FIRST和LAST名称,如果有3,则将其解释为FIRST,MIDDLE和LAST。

问题在于,简单的解决方案不会是100%正确的解决方案,因为有人总是可以输入带有更多标记的名称,或者可以包含标题,姓氏和空格(可以吗?)等。提出了大多数情况下大多数名称都适用的解决方案,但不是绝对的解决方案。

我将遵循Shad的建议来拆分输入字段。

我们可能真的不需要做任何花哨的事情。这样的事情应该起作用。

Name = Name.Trim();

    arrNames = Name.Split(' ');

    if (arrNames.Length > 0) {
        GivenName = arrNames[0];
    }
    if (arrNames.Length > 1) {
        FamilyName = arrNames[arrNames.Length - 1];
    }
    if (arrNames.Length > 2) {
        MiddleName = string.Join(" ", arrNames, 1, arrNames.Length - 2);
    }

我们可能还需要先检查标题。

我们不希望这样做,除非我们只是要联系一种文化的人。

例如:

Guido van Rossum的姓氏是van Rossum。

MIYAZAKI Hayao的名字叫Hayao。

我们可能要做的最大成功就是剥离常见的标题和称呼,然后尝试一些启发式方法。

即使这样,最简单的解决方案是仅存储全名,或者分别要求提供的姓氏和姓氏。

这是一个傻瓜差事。太多的例外情况无法确定性地执行此操作。如果我们这样做是为了对列表进行预处理,以供进一步审核,那么我相信少即是多。

  • 去除称呼,称谓和代词后缀(大正则表达式或者几个小正则表达式)
  • 如果只有一个名字,那就是"姓氏"。
  • 如果仅将两个名字分开,则最后一个。
  • 如果最初将三个标记和中间标记分开,则将它们首先,中间,最后分开
  • 手工整理其余部分。

几乎可以保证,任何进一步的处理都将创造更多的工作,因为我们必须重新组合处理过程中的拆分工作。

我知道很难做到这一点,但是如果我们为用户提供了一种编辑结果的方法(例如,弹出窗口以编辑名称(如果猜对的话)),并且在大多数情况下仍然猜对...当然是很难的猜测。

从理论上看问题时,很容易说"不做",但有时情况则相反。具有名称的所有部分(标题,名字,中间,最后一个,后缀,仅举几例)的字段可能会占用大量屏幕空间,并与地址问题(另一天的主题)结合可以真正弄清应该是一个干净,简单的用户界面。

我猜答案应该是"除非绝对必要,否则不要这样做,如果这样做,请保持简单(此处已发布了一些方法),并在需要时为用户提供了编辑结果的方法。"

我必须这样做。实际上,要比这难得多,因为有时"名称"将是" Smith,John"或者" Smith John"而不是" John Smith",或者根本不是一个人的名字,而是公司的名称。而且它必须自动执行,而用户没有机会进行更正。

我最终要做的是想出一个可以列出名称的模式的有限列表,例如:
最后,第一个中间人
倒数第一
第一中首末
最后,第一中
第一中最后
倒数第一

也把你的先生,小儿子扔在那里。假设我们最终遇到了十几种模式。

我的应用程序有一个常用名,常用名(我们可以在网上找到这些),常用标题,常用后缀(jr,sr,md)的字典,并使用它们可以对模式进行真正的猜测。我不是那么聪明,我的逻辑也不是那么花哨,但是,创建一些可以在99%以上的时间猜对的逻辑并不难。

如果我们只需要执行此操作,则将猜测作为可选选项添加到UI中。这样,我们可以告诉用户如何解析名称,并让他们从我们提供的列表中选择不同的解析。

请参阅更多讨论(几乎恰好在一年前):
http://discuss.joelonsoftware.com/default.asp?design.4.551889.41

我同意,对此没有简单的解决方案。但是我在VB 5.0的Microsoft KB文章中发现了一种糟糕的方法,它是此处讨论的大部分讨论的实际实现:http://support.microsoft.com/kb/168799

像这样的东西可以在紧要关头使用。

理解这是一个坏主意,我在perl中编写了此正则表达式,这对我来说是最有效的。我已经过滤掉公司名称。
以vcard格式输出:(hon_prefix,gived_name,additional_name,family_name,hon后缀)

/^ \s*
    (?:((?:Dr.)|(?:Mr.)|(?:Mr?s.)|(?:Miss)|(?:2nd\sLt.)|(?:Sen\.?))\s+)? # prefix
    ((?:\w+)|(?:\w\.)) # first name
(?: \s+ ((?:\w\.?)|(?:\w\w+)) )?  # middle initial
(?: \s+ ((?:[OD]['’]\s?)?[-\w]+))    # last name
(?: ,? \s+ ( (?:[JS]r\.?) | (?:Esq\.?) | (?: (?:M)|(?:Ph)|(?:Ed) \.?\s*D\.?) | 
         (?: R\.?N\.?) | (?: I+) )  )? # suffix
\s* $/x

笔记:

  • 无法处理IV,V,VI
  • 前缀,后缀的硬编码列表。从约2000个名称的数据集演变而来
  • 不处理多个后缀(例如,MD,PhD)
  • 专为美国名称设计-在罗马化的日本名称或者其他命名系统上无法正常使用

没有100%的方法可以做到这一点。

我们可以在空格上分开,尝试理解所有想要的名称,但是当涉及到该名称时,有时会弄错它。如果这足够好,请在此处寻求任何答案,让我们可以拆分。

但是有些人的名字会像"约翰·韦恩·奥尔森",其中"约翰·韦恩"是第一个名字,而其他人的名字会像"约翰·韦恩·奥尔森",其中"韦恩"是他们的中间名。该名称中没有任何内容可以告诉我们哪种解释方式。

就是那样子。这是一个模拟世界。

我的规则很简单。

最后一部分->姓氏
如果还有剩余部分,请取最后一部分->中间名
剩下的->名字

但是不要以为这将是100%准确的,任何其他硬编码的解决方案也不会。我们将需要具有让用户自己编辑此文件的能力。

我们在公司中使用了一些外接程序来完成此任务。我最终创建了一种方法,可以为不同的客户在不同的导入中实际指定名称的格式。根据我的经验,有一家公司的工具非常值得,并且在解决这个问题时确实令人难以置信。它位于:http://www.softwarecompany.com/,效果很好。使用任何统计方法来执行此操作的最有效方法是,用逗号或者空格分隔字符串,然后:1.删除标题和前缀2.删除后缀3,按(2名称= F的顺序解析名称&L,3个名称= FML或者LMF),具体取决于string()的顺序。