C# 在C中从全名字符串中分离firstname和lastname#
我正在做一个网站迁移,包括从全名中提取firstname和lastname。鉴于这些都是由最终用户创建的,因此存在各种排列(尽管英语和一般不太奇怪)。大多数情况下,我可以将第一个单词作为firstname,最后一个单词作为lastname,但偶尔会出现前缀和后缀的例外情况。在浏览数据并试图了解所有可能的异常时,我意识到这是一个常见的问题,以前至少已经部分解决了很多次 在重新发明轮子之前,是否有人拥有任何适用于它们的正则表达式或有用的代码?性能不是一个考虑因素,因为这是一个一次性实用程序 要处理的典型值: 杰森·布里格斯, J.D.史密斯, 约翰,我的公民, J.斯科特·迈尔斯, 比尔·杰克布森三世, 约翰·米尔斯先生C# 在C中从全名字符串中分离firstname和lastname#,c#,regex,string,C#,Regex,String,我正在做一个网站迁移,包括从全名中提取firstname和lastname。鉴于这些都是由最终用户创建的,因此存在各种排列(尽管英语和一般不太奇怪)。大多数情况下,我可以将第一个单词作为firstname,最后一个单词作为lastname,但偶尔会出现前缀和后缀的例外情况。在浏览数据并试图了解所有可能的异常时,我意识到这是一个常见的问题,以前至少已经部分解决了很多次 在重新发明轮子之前,是否有人拥有任何适用于它们的正则表达式或有用的代码?性能不是一个考虑因素,因为这是一个一次性实用程序 要处理的
更新:虽然这是一个常见问题,但典型的解决方案似乎涉及处理大多数情况,并手动清洁其余情况
(鉴于这个问题必须经历的频率,我原本期望在那里找到一个实用库,但是我自己找不到一个谷歌)
如果这是一次性的交易,那么我会强烈地考虑付钱给某个专家来替你做。 他们将有处理结构不良数据集的经验我与他们没有任何关系,但我提供的服务似乎是为这类事情量身定做的。这可能是不可能做到的(可靠的) 即使你能为一些名字写下这些,你也会在某个时候得到一个西班牙人,他会写下两个姓氏。或者有些人(忘了是哪个国籍)会写上“姓氏”。或者其他许多情况中的一种
你能做的最好的方法是将两个单词分成名字和姓氏,然后手动检查其余的单词(你自己,或者雇佣一些专业人士).这是一个不确定的问题(或者我喜欢称之为Oracle问题),无法以可靠的方式解决。这是因为存在着名和姓的名字,例如斯坦利、杰克逊等,但可以尝试一下。你需要编写一个学习程序,给你一组名字和姓氏,它将维护一个这些名字的字典,根据名字的概率映射 现在,传递所有要迁移的值,并使用这些概率,您可以在名字和姓氏之间得到合理的划分。此外,如果某个特定名称变得模棱两可(完全由您来定义模棱两可,但我会将其定义为我获得的所有概率值的底部30%),那么您可以将其标记以供以后查看 希望这有帮助
干杯 我的建议如下:
希望这对您有所帮助。如果您只有少数用户(最快的方法是一种混合算法-人工方法。你不想把时间花在构建一个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;
}