Регулярное выражение для классификации частей адреса службы? - PullRequest
2 голосов
/ 16 марта 2009

Приложение, которое я пишу, работает с адресами служебных сервисов, и сейчас я заставляю пользователя знать достаточно, чтобы разделить части адреса и поместить их в соответствующие поля перед добавлением в базу данных. Это должно быть сделано таким образом в целях сортировки, потому что прямая сортировка по алфавиту не всегда правильна, когда в адресе есть предварительное направление. Например, прямо сейчас, если пользователь хочет ввести адрес службы 123 N Main St , он будет вводить его как:

  • Номер улицы = 123
  • Предварительное направление = N
  • Название улицы = Главная
  • Тип улицы = 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 ]

1 голос
/ 16 марта 2009

У меня нет набора адресов для (простого) тестирования, но здесь есть что попробовать, по крайней мере. Это может быть слишком разрешительным в некоторых местах или слишком ограничительным в других, но вы должны быть в состоянии настроить его. Вам определенно нужно настроить список предустановок, но вам придется указать их явно. Кроме того, убедитесь, что в параметрах регулярных выражений регистр не учитывается.

^(?<StreetNumber>[0-9]+)\s*(?<Predirection>(n)|(s)|(e)|(w)|(north)|(south)|(east)|(west))?\s+(?<StreetName>[a-z0-9 -'.]+)\s+(?<StreetType>[a-z.]+)$

В действительности, вероятно, было бы лучше делегировать это парсеру адресов, если это возможно, как тот, который предложил NoahD. Возможно, вам придется немного покопаться, чтобы найти что-то для .NET, но если вы не можете ничего найти, то я бы наверняка использовал регулярное выражение.

edit: do'h, \ s, not / s

edit: изменено регулярное выражение для более семантической группировки. Вы можете получить доступ к значениям группы следующим образом:

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"];
} 
0 голосов
/ 17 марта 2009

Подойдет ли геокодирование от Google для вашего приложения?

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

0 голосов
/ 16 марта 2009

Вы можете сделать это в Perl, используя Geo :: StreetAddress :: US

Например:

  my $hashref = Geo::StreetAddress::US->parse_address(
                "1600 Pennsylvania Ave, Washington, DC" );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...