Ява: Разбор австралийских уличных адресов - PullRequest
1 голос
/ 01 марта 2010

В поисках быстрого и грязного способа разбить австралийские уличные адреса на части:
3A/45 Jindabyne Rd, Oakleigh, VIC 3166

следует разделить на:
"3A", 45, "Jindabyne Rd" "Oakleigh", "VIC", 3166

Названия пригородов могут содержать несколько слов, как и названия улиц.


См .: Разобрать адрес Steet на компоненты

Должен быть на Java, не может делать http-запросы (например, к веб-API).


РЕДАКТИРОВАТЬ: Предположим, что указанный формат всегда соблюдается. У меня нет проблем с тем, чтобы выкладывать неправильно отформатированные строки обратно пользователю с сообщением о том, что он следует формату (который я описал выше).

Ответы [ 6 ]

9 голосов
/ 02 марта 2010

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

Вы действительно хотите попробовать (самостоятельно) проанализировать каждую возможную комбинацию Richmond, Victoria, 3121 и Richmond 3121 VIC и Richmond VIC, 3121 и т. Д.? И это только гранулярность пригорода!

Адреса еще хуже. Конечно, большинство людей поставили бы 7/21 Smith St за единицу или 29-33 Jones St за местоположение, охватывающее несколько улиц, но люди не согласны. Является ли 1-5 Brown St единица 1 под номером 5 или локация от 1 до 5 на этой улице? Является ли 7A отдельным подразделенным адресом улицы или Единицей A в # 7?

Сопоставление адресов не простая проблема, и если ваш набор данных представляет собой свободный текст, введенный конечным пользователем, я бы не стал беспокоиться, если у вас нет тривиального объема данных или вас не волнует Точность (или, наоборот, много времени для ручной очистки). Если нет, передайте это программному обеспечению, которое сделает эту работу за вас.

В австралийской почте есть нечто, называемое Файл почтовых адресов (PAF) , в котором содержится каждое действительное место доставки в Австралии. Существует ряд программных библиотек, которые выполнят для вас синтаксический анализ + сопоставление и либо дадут вам окончательный ответ (включая все отдельные компоненты адреса, как вам нужно), либо предоставят список возможных совпадений на ваш выбор. если адрес не существует или неоднозначен. Один известный мне пример - QAS Batch (никак не связан с ними, в прошлом оценивал их программное обеспечение, но в итоге его не использовал), но это только один пример; есть список других доступных через веб-сайт PAF.

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

Если это так, эй, да, регулярное выражение.

3 голосов
/ 02 марта 2010

Учитывая ваш ответ на мой другой ответ, это должно быть сделано для строго отформатированного случая, который вы указали:

    String sample = "3A/45 Jindabyne Rd, Oakleigh, VIC 3166";
    Pattern pattern = Pattern.compile("(([^/ ]+)/)?([^ ]+) ([^,]+), ([^,]+), ([^ ]+) (\\d+)");
    Matcher m = pattern.matcher(sample);
    if (m.find()) {
        System.out.println("Unit: " + m.group(2));
        System.out.println("Number: " + m.group(3));
        System.out.println("Street: " + m.group(4));
        System.out.println("Suburb: " + m.group(5));
        System.out.println("State: " + m.group(6));
        System.out.println("Postcode: " + m.group(7));
    } else {
        throw new IllegalArgumentException("WTF");
    }

Это работает, если вы удалите «3A /» (в этом случае m.group(2) будет нулевым), если номер улицы будет «45A» или «45 -47», если мы добавим пробел к дороге (' Jindabyne East Rd ') или в пригород ("Oakleigh South").

Просто чтобы объяснить это регулярное выражение, если вы не знакомы с регулярными выражениями:

(([^/ ]+)/)? является эквивалентом ([^/ ]+/)?, то есть «всего, кроме косой черты или пробела, за которым следует косая черта». Знак вопроса делает его необязательным (поэтому может отсутствовать целое предложение), а дополнительные скобки в окончательной версии предназначены для создания меньшей внутренней группы без косой черты для последующего извлечения.

([^ ]+) означает «захватить все, что не является пробелом (за которым следует пробел)» - это номер улицы.

([^,]+), - это «захватить все, что не является запятой (за которой следуют запятая и пробел)» - это название улицы. В названии улицы все допустимо, если это не запятая.

([^,]+), снова то же самое, в этом случае, чтобы захватить пригород.

([^ ]+) захватывает следующую непробельную строку (сокращение состояния) и пропускает пробел после нее.

(\\d+) округляется путем захвата любого количества цифр (почтовый индекс)

Надеюсь, это полезно.

1 голос
/ 01 марта 2010

Хм, вероятно, довольно сложно, потому что формат не очень хорошо определен.

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

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

Редактировать: Кстати, чтобы использовать регулярные выражения в Java, используйте методы из пакета java.util.regex. Просто подумал, что упомяну это ...

0 голосов
/ 08 мая 2017

Я создал регулярное выражение, которое извлекает компоненты адреса (например, номер объекта, номер улицы, название улицы, включая пригород, штат и почтовый индекс), это работает на австралийских адресах, но его можно легко настроить для других адресов, единственная вещь обновить для других адресов является государственная часть. https://regex101.com/library/5bj4wi

0 голосов
/ 09 июня 2010

Для коммерческого решения вы можете попробовать address-parser.com .

0 голосов
/ 01 марта 2010

Вы можете использовать String.split , сначала с ,, затем с . или /.

...