Kei*_*ius 30 string parsing database-design
许多联系人管理程序都这样做 - 你输入一个名字(例如,"John W. Smith"),它会自动将其分解为:
名字:约翰
中间名: W.
姓:史密斯
同样,它也会找出像"简·史密斯夫人"和"约翰·多伊博士"这样的事情.也正确(假设您允许名称中包含"prefix"和"suffix"等字段).
我认为这是人们想要做的相当普遍的事情......所以问题是......你会怎么做?有一个简单的算法吗?也许正则表达式?
我正在使用.NET解决方案,但我并不挑剔.
更新:我感谢没有简单的解决方案可以涵盖所有边缘案例和文化...但是,为了论证,你需要说明你需要这个名字(填写表格 - 比如说,税收或其他政府表格 - 是一种情况,您必须将名称输入固定字段,无论您是否喜欢),但您不一定要强迫用户将其名称输入到离散字段中(减少输入=更容易新手用户).
你想让程序"猜测"(尽可能最好)在第一个,中间的,最后一个等等.如果可以的话,看看Microsoft Outlook如何为联系人做这个 - 它让你输入名字,但是如果你需要澄清,你可以打开一个额外的小窗口.我会做同样的事情 - 给用户提供窗口以防他们想要以离散的部分输入名称 - 但允许在一个框中输入名称并进行涵盖大多数常见名称的"最佳猜测" .
sha*_*dit 32
如果你必须进行这种解析,我相信你会在这里得到很多好的建议.
我的建议是 - 不要做这个解析.
而是创建输入字段,以便信息已经分离出来.有标题,名字,中间名,姓氏,后缀等单独的字段.
ese*_*elk 17
我知道这是旧的,可能是我已经找不到的地方的答案,但由于我找不到任何对我有用的东西,这就是我提出的,我认为它与Google Contacts和Microsoft Outlook非常相似.它不能很好地处理边缘情况,但对于一个好的CRM类型的应用程序,总是可以要求用户解决这些问题(在我的应用程序中我实际上一直有单独的字段,但我需要这个来从另一个应用程序导入数据只有一个字段):
public static void ParseName(this string s, out string prefix, out string first, out string middle, out string last, out string suffix)
{
prefix = "";
first = "";
middle = "";
last = "";
suffix = "";
// Split on period, commas or spaces, but don't remove from results.
List<string> parts = Regex.Split(s, @"(?<=[., ])").ToList();
// Remove any empty parts
for (int x = parts.Count - 1; x >= 0; x--)
if (parts[x].Trim() == "")
parts.RemoveAt(x);
if (parts.Count > 0)
{
// Might want to add more to this list
string[] prefixes = { "mr", "mrs", "ms", "dr", "miss", "sir", "madam", "mayor", "president" };
// If first part is a prefix, set prefix and remove part
string normalizedPart = parts.First().Replace(".", "").Replace(",", "").Trim().ToLower();
if (prefixes.Contains(normalizedPart))
{
prefix = parts[0].Trim();
parts.RemoveAt(0);
}
}
if (parts.Count > 0)
{
// Might want to add more to this list, or use code/regex for roman-numeral detection
string[] suffixes = { "jr", "sr", "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix", "x", "xi", "xii", "xiii", "xiv", "xv" };
// If last part is a suffix, set suffix and remove part
string normalizedPart = parts.Last().Replace(".", "").Replace(",", "").Trim().ToLower();
if (suffixes.Contains(normalizedPart))
{
suffix = parts.Last().Replace(",", "").Trim();
parts.RemoveAt(parts.Count - 1);
}
}
// Done, if no more parts
if (parts.Count == 0)
return;
// If only one part left...
if (parts.Count == 1)
{
// If no prefix, assume first name, otherwise last
// i.e.- "Dr Jones", "Ms Jones" -- likely to be last
if(prefix == "")
first = parts.First().Replace(",", "").Trim();
else
last = parts.First().Replace(",", "").Trim();
}
// If first part ends with a comma, assume format:
// Last, First [...First...]
else if (parts.First().EndsWith(","))
{
last = parts.First().Replace(",", "").Trim();
for (int x = 1; x < parts.Count; x++)
first += parts[x].Replace(",", "").Trim() + " ";
first = first.Trim();
}
// Otherwise assume format:
// First [...Middle...] Last
else
{
first = parts.First().Replace(",", "").Trim();
last = parts.Last().Replace(",", "").Trim();
for (int x = 1; x < parts.Count - 1; x++)
middle += parts[x].Replace(",", "").Trim() + " ";
middle = middle.Trim();
}
}
Run Code Online (Sandbox Code Playgroud)
对不起,代码很长很难看,我还没有去清理它.它是一个C#扩展,所以你会像以下一样使用它:
string name = "Miss Jessica Dark-Angel Alba";
string prefix, first, middle, last, suffix;
name.ParseName(out prefix, out first, out middle, out last, out suffix);
Run Code Online (Sandbox Code Playgroud)
Ste*_*ken 10
对此没有简单的解决方案.名称构造因文化而异,甚至在英语世界中也有前缀和后缀,这些前缀和后缀不一定是名称的一部分.
一个基本的方法是在字符串的开头寻找敬意(例如,"Hon.John Doe")和最后的数字或其他字符串(例如,"John Doe IV","John Doe Jr."),但是你所能做的就是应用一套启发式方法,并希望最好.
查找未处理名称列表并根据它测试算法可能很有用.不过,我不知道那里有什么预先包装好的东西.
你可能不需要做任何真正的事情.这样的事情应该有效.
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);
}
Run Code Online (Sandbox Code Playgroud)
您可能还想先检查标题.
| 归档时间: |
|
| 查看次数: |
28552 次 |
| 最近记录: |