Регулярное выражение: разобрать название улицы / номер - PullRequest
3 голосов
/ 16 февраля 2011

C # /. NET 2.0

Мне нужно разобрать строку, содержащую название улицы и номер дома, в два отдельных значения.

in: "Streetname 1a"         out:  "streetname"  "1a"
    "Street name 1a"              "street name" "1a"
    "Street name 1 a"             "street name" "1 a"

Мой первый выбор был разбить строку, где я нашел символ "", но это не сработает для второго случая.

result[0] = trimmedInput.Substring(0, splitPosition).Trim();
result[1] = trimmedInput.Substring(splitPosition + 1).Trim();

Каков наилучший способ сделать это? Могу ли я использовать регулярные выражения?

Спасибо

Ответы [ 5 ]

8 голосов
/ 16 февраля 2011

^(.+)\s(\S+)$ должен сделать трюк

РЕДАКТИРОВАТЬ: это будет работать, если в номере дома не должно быть пробелов. В противном случае эта проблема не может быть решена программно, так как программа никогда не узнает семантику строковых токенов.

Адреса домов грязные и непоследовательные. Я работал с адресными данными и, честно говоря, если у вас нет данных в нормализованной форме, вы в основном облажались.

^(.+)\s(\d+(\s*[^\d\s]+)*)$ охватит еще несколько случаев, но подобный шаблон - банка червей, если я когда-либо видел ее.

2 голосов
/ 26 января 2012

Как заявил Dyppl, адреса улиц грязные.Но если ваши адресные данные представляют адреса США и у вас есть полный адрес (включая город, штат и / или почтовый индекс), вы можете использовать службу проверки адресов для анализа (и проверки!) И стандартизации компонентов.Я работаю на SmartyStreets , провайдер проверки адресов.Вот небольшой пример C #, который я недавно написал, который вызывает наш API LiveAddress:

https://github.com/smartystreets/LiveAddressSamples/blob/master/c-sharp/street-address.cs

Вот результирующий вывод для этого примера (обратите внимание, что название улицы и основной номер анализируются враздел «компоненты»):

[
    {
        "input_index": 0,
        "candidate_index": 0,
        "delivery_line_1": "3214 N University Ave",
        "last_line": "Provo UT 84604-4405",
        "delivery_point_barcode": "846044405140",
        "components": {
            "primary_number": "3214",
            "street_predirection": "N",
            "street_name": "University",
            "street_suffix": "Ave",
            "city_name": "Provo",
            "state_abbreviation": "UT",
            "zipcode": "84604",
            "plus4_code": "4405",
            "delivery_point": "14",
            "delivery_point_check_digit": "0"
        },
        "metadata": {
            "record_type": "S",
            "county_fips": "49049",
            "county_name": "Utah",
            "carrier_route": "C016",
            "congressional_district": "03",
            "latitude": 40.27586,
            "longitude": -111.6576,
            "precision": "Zip9"
        },
        "analysis": {
            "dpv_match_code": "Y",
            "dpv_footnotes": "AABBR1",
            "dpv_cmra": "Y",
            "dpv_vacant": "N",
            "ews_match": false
        }
    }
]

Мы предоставляем абсолютно бесплатную подписку для пользователей с низким уровнем использования.Вот ссылка, которая объясняет все поля:

http://wiki.smartystreets.com/liveaddress_api_users_guide#json-responses

РЕДАКТИРОВАТЬ: включены поля широты / долготы (недавно выпущен).

1 голос
/ 16 февраля 2011

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

  • Адрес улицы состоит из имени и номера.
  • Имя всегда появляется первым.
  • Имя состоит из одного или нескольких слов, разделенных пробелами.
  • Число - это число, за которым следует дополнительная буква.

Из комментария последняя точка не совсем верна, потому что цифра и буква части улицы могут быть разделены пробелами.

Если вы не можете гарантировать порядок названия и номера улицы, а также то, что слова в названии улицы не содержат цифр, тогда я не совсем уверен, что вам что-то поможет.

Следующее регулярное выражение должно охватывать большинство случаев:

Regex reggie = new Regex(@"^(?<name>\w[\s\w]+?)\s*(?<num>\d+\s*[a-z]?)$", RegexOptions.IgnoreCase)
0 голосов
/ 16 февраля 2011

Предполагается, что все ваши «адреса» будут отформатированы хотя бы одним из способов, упомянутых выше.

string address = "Streetname 1a"

string street = Regex.Replace(address, "^[^0-9]+", "");

string number = address.Replace(street, "");

Затем обрежьте оба значения.

0 голосов
/ 16 февраля 2011

Сначала вы должны попытаться найти число, используя String.LastIndexOf() для разделения на возможную позицию.

После этого вы должны проверить, содержит ли какой-либо символ в этой последней группе такие цифры, как splittedValue.Any(c => Char.IsDigit(c));. Поэтому, если вы обнаружите какие-либо числа в этой последней группе, вы можете быть почти уверены, что вы сделали правильное разбиение, но, возможно, есть адреса, которые не соответствуют этому поведению.

Обновление

Если у вас действительно есть такие зашумленные данные, которые должны быть нормализованы, я думаю, что вы не можете сделать что-то лучше, чем сказал @Dyppl, и использовал какое-то сложное регулярное выражение, которое должно эволюционировать по полученным образцам, которые не будут работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...