正则表达式对服务地址的各个部分进行分类?
Posted
技术标签:
【中文标题】正则表达式对服务地址的各个部分进行分类?【英文标题】:Regular expression to categorize the parts of a service address? 【发布时间】:2010-10-13 17:00:25 【问题描述】:我正在编写的应用程序处理公用事业服务地址,现在我强迫用户知道足够的知识来分离地址的各个部分,并在添加到数据库之前将它们放在适当的字段中。出于排序目的,必须以这种方式进行排序,因为当地址中有预先指示时,直接按字母顺序排序并不总是正确的。例如,现在如果用户想输入服务地址 123 N Main St,他们将输入为:
街道编号 = 123 预方向 = N 街道名称 = 主要 街道类型 = St我尝试通过使用 Split 函数并遍历每个部分来将此地址分成几个部分。到目前为止我所拥有的如下:
公共共享函数 ParseServiceAddress(ByVal Address As String) As String() '这假定一个有效的地址 - 101 N Main St South Dim strResult(5) As String '0=st_num, 1=predir, 2=st_name, 3=st_type, 4=postdir 将 strParts() 调暗为字符串 暗淡 strSep() As Char = Char.Parse(" ") 将 i 调暗为整数 将 j 调暗为整数 = 0 地址 = 地址.Trim() strParts = Address.Split(strSep) '使用空格分割 对于 i = 0 到 strParts.GetUpperBound(0) If Integer.TryParse(strParts(i), j) 那么 '这是一个号码,是门牌号码吗? 如果 i = 0 那么 '我们知道这是门牌号码 strResult(0) = strParts(i) 别的 '街道名称的一部分 strResult(2) = strResult(2) & " " & strParts(i) 万一 别的 选择案例 strParts(i).ToUpper() 案例“TH”、“ND” '知道这是街道名称的一部分 strResult(2) = strResult(2) & strParts(i) 案例“NORTH”、“SOUTH”、“EAST”、“WEST”、“N”、“S”、“E”、“W” '这是预先指示吗? 如果 i = 1 那么 strResult(1) = strParts(i) ElseIf i = strParts.GetUpperBound(0) 然后 '这是发帖方向 strResult(4) = strParts(i) 别的 '名字的一部分 strResult(2) = strResult(2) & strParts(i) 万一 其他情况 如果 i = strParts.GetUpperBound(0) 那么 '街道类型 strResult(3) = strParts(i) 别的 '街道名称的一部分 strResult(2) = strResult(2) & " " & strResult(i) 万一 结束选择 万一 接下来我 返回字符串结果 结束函数当给出一个不稳定的地址时,我发现这种方法很麻烦、很慢,甚至完全错误。我想知道我在这里尝试做的是否是正则表达式的一个很好的应用程序?诚然,我以前从未在任何事情中使用过正则表达式,并且在这方面完全是新手。
提前感谢您的帮助。 :)
编辑 - 似乎我越来越需要一个解析器,而不仅仅是正则表达式。有谁知道 .NET 中有什么好的地址解析器库?写我们自己的东西现在还没有考虑到,如果真的到了那一步,就会被搁置一旁。
【问题讨论】:
前向总是一个字母吗? @Stuart B - 不,有时人们会像“123 South Main St”一样输入它们 @Heather - 这绝对让这个难题更加棘手!您肯定必须有一个已定义的可接受的前向列表。 我想知道,你真的需要子字段吗?你有什么理由不把它放在一个字符串中,特别是因为用户似乎无论如何都会以不同的方式输入相同的名称(即使忽略拼写错误和通常的拼写恐惧)? @Svante - 我需要子字段,因为单个地址字段上的字母排序不会将街道按正确的数字顺序排列。示例 - “1123 Main St”将按升序排列在“12 Main St”之前 【参考方案1】:你可以在 Perl 中使用 Geo::StreetAddress::US 来做到这一点
例如:
我的 $hashref = Geo::StreetAddress::US->parse_address( “华盛顿特区宾夕法尼亚大道 1600 号”);【讨论】:
太糟糕了,这是在 VB.NET 中,因为这几乎正是我正在寻找的。您不知道 .NET 中是否有任何解析器库? 其实这可能是更好的线程:***.com/questions/16413/…【参考方案2】:我没有一组可以(轻松)测试的地址,但至少可以尝试一下。它可能在某些地方过于宽松或在其他地方过于严格,但您应该能够对其进行调整。您肯定需要调整前向列表,但您将必须明确指定这些。此外,请务必将您的正则表达式选项设置为不区分大小写。
^(?<StreetNumber>[0-9]+)\s*(?<Predirection>(n)|(s)|(e)|(w)|(north)|(south)|(east)|(west))?\s+(?<StreetName>[a-z0-9 -'.]+)\s+(?<StreetType>[a-z.]+)$
但实际上,如果可能的话,最好将其委托给地址解析器,就像 NoahD 建议的那样。您可能需要进行一些挖掘才能为 .NET 找到一些东西,但如果您找不到任何东西,那么我肯定会使用正则表达式。
编辑:do'h,\s,而不是 /s
编辑:更改正则表达式以获得更多语义分组。您可以像这样访问组值:
string address = "123 n main st";
Regex regex = new Regex("insert the regex above here", RegexOptions.IgnoreCase);
MatchCollection matches = regex.Matches(address);
foreach(Match match in matches)
string streetAddress = matches.Groups["StreetAddress"];
string predirection = matches.Groups["Predirection"];
string streetName = matches.Groups["StreetName"];
string streetType = matches.Groups["StreetType"];
【讨论】:
嗯...我想我以前不太了解正则表达式的作用。正如你所说,地址解析器可能是我需要的。将此表达式插入 .NET 的 Regex 对象可以很好地验证我的输入,因此对该帐户 +1。谢谢您的帮助。 :) 其实,你可以使用正则表达式来提取字符串的一部分。我有点草率地写了这篇文章,所以可能很难知道要拉哪些组。只需在 Google 上搜索“C# Regex Groups”或其他内容。 至于地址解析器,我认为 geocoder.us 有一个。不过,我不知道您是否必须为此付费。 这实际上对我有很大帮助,但并不能完全解决问题。我认为资源将暂时分配给更好的努力。再次感谢您花时间帮助我解决这个问题。【参考方案3】:使用来自 Google 的地理编码是否适合您的应用?
http://code.google.com/apis/maps/documentation/services.html#Geocoding_Structured
【讨论】:
以上是关于正则表达式对服务地址的各个部分进行分类?的主要内容,如果未能解决你的问题,请参考以下文章