正则表达式对服务地址的各个部分进行分类?

时间:2009-03-16 19:54:50

标签: vb.net regex parsing

我正在编写的应用程序处理实用程序服务地址,现在我强迫用户知道足够的分离地址的各个部分,并在添加到数据库之前将它们放在适当的字段中。必须以这种方式进行排序,因为当地址中有预先指示时,直接的字母排序并不总是正确的。例如,现在如果用户想要输入服务地址 123 N Main St ,他们会将其输入为:

  • 街道号码= 123
  • Pre-direction = N
  • Street Name = Main
  • 街道类型= St

我试图通过使用Split函数并遍历每个部分将此地址分成其部分。我到目前为止的内容如下:

Public Shared Function ParseServiceAddress(ByVal Address As String) As String()
        'this assumes a valid address - 101 N Main St South
        Dim strResult(5) As String  '0=st_num, 1=predir, 2=st_name, 3=st_type, 4=postdir
        Dim strParts() As String
        Dim strSep() As Char = {Char.Parse(" ")}
        Dim i As Integer
        Dim j As Integer = 0
        Address = Address.Trim()
        strParts = Address.Split(strSep)  'split using spaces
        For i = 0 To strParts.GetUpperBound(0)
            If Integer.TryParse(strParts(i), j) Then
                'this is a number, is it the house number?
                If i = 0 Then
                    'we know this is the house number
                    strResult(0) = strParts(i)
                Else
                    'part of the street name
                    strResult(2) = strResult(2) & " " & strParts(i)
                End If
            Else
                Select Case strParts(i).ToUpper()
                    Case "TH", "ND"
                        'know this is part of the street name
                        strResult(2) = strResult(2) & strParts(i)
                    Case "NORTH", "SOUTH", "EAST", "WEST", "N", "S", "E", "W"
                        'is this a predirection?
                        If i = 1 Then
                            strResult(1) = strParts(i)
                        ElseIf i = strParts.GetUpperBound(0) Then
                            'this is the post direction
                            strResult(4) = strParts(i)
                        Else
                            'part of the name
                            strResult(2) = strResult(2) & strParts(i)
                        End If
                    Case Else
                        If i = strParts.GetUpperBound(0) Then
                            'street type
                            strResult(3) = strParts(i)
                        Else
                            'part of the street name
                            strResult(2) = strResult(2) & " " & strResult(i)
                        End If
                End Select
            End If
        Next i
        Return strResult
    End Function
我发现这个方法很麻烦,很慢,甚至在给出一个不稳定的地址时完全错误。我想知道我在这里尝试做什么对正则表达式来说是一个很好的应用程序?不可否认,我从来没有在任何事情上使用正则表达式,并且在这方面是新手。

提前感谢您的帮助。 :)

编辑 - 似乎越来越像我将需要一个解析器,而不仅仅是正则表达式。有谁知道.NET中任何好的地址解析器库?写我们自己的东西现在不在卡片中,如果出现的话会被发送到后面。

3 个答案:

答案 0 :(得分:1)

我没有一套地址可以(轻松)测试,但这里至少要尝试一下。它可能在某些地方过于宽松或在其他地方过于严格,但你应该能够调整它。你肯定需要调整预测列表,但必须明确指定。另外,请务必将正则表达式选项设置为不区分大小写。

^(?<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,not / 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"];
} 

答案 1 :(得分:0)

您可以使用Geo::StreetAddress::US

在Perl中执行此操作

例如:

  my $hashref = Geo::StreetAddress::US->parse_address(
                "1600 Pennsylvania Ave, Washington, DC" );

答案 2 :(得分:0)

使用Google的地理编码是否适合您的应用?

http://code.google.com/apis/maps/documentation/services.html#Geocoding_Structured