2

寻找一种快速而肮脏的方法来将澳大利亚街道地址解析成各个部分:
3A/45 Jindabyne Rd, Oakleigh, VIC 3166

应拆分为:
"3A", 45, "Jindabyne Rd" "Oakleigh", "VIC",3166

郊区名称可以有多个单词,街道名称也可以。


请参阅:将 Steet 地址解析为组件

必须使用 Java,不能发出 http 请求(例如对 Web API)。


编辑:假设始终遵循指定的格式。我对向用户吐出格式不正确的字符串并告诉他们遵循格式(我在上面已经描述过)的消息没有任何问题。

4

7 回答 7

8

老实说,你在这里给自己设定了一个相当西西弗斯的挑战,我不确定这是否值得。除非您的数据来自已知来源,并且具有非常明确的格式,否则您将获得完全无用的数据。如果您正在处理自由文本,人们会以您不相信的方式搞砸他们的地址。

您真的想尝试(自己)解析和等的所有可能Richmond, Victoria, 3121组合Richmond 3121 VICRichmond VIC, 3121?这只是郊区粒度!

地址更糟。当然,大多数人会7/21 Smith St选择一个单元,或者29-33 Jones St一个跨越多个街道号码的位置,但人们并不一致。单元 1是1-5 Brown St在 5 号,还是在那条街上从 #1 到 #5 的位置?是7A单独的细分街道地址,还是#7 的 A 单元?

地址匹配不是一个简单的问题,如果您的数据集是最终用户输入的自由文本,我真的不会打扰,除非您有少量数据或不太关心准确性(或者,有大量时间用于手动清理)。如果没有,请将其交给一个为您工作的软件。

澳大利亚邮政有一个称为邮政地址文件 (PAF) 的东西,其中包含澳大利亚的每个有效投递地点。有许多软件库将为您进行解析+匹配,并为您提供明确的答案(包括所有单独的地址组件,如您所追求的)或提供潜在匹配列表供您选择如果地址不存在或不明确。我知道的一个例子是QAS Batch(以任何方式与他们无关,过去评估过他们的软件但最终没有使用它)但这只是一个例子;可以通过 PAF 网站访问其他人的列表。

不能强烈推荐你不要浪费你的时间,除非它是微不足道的。

如果是,嘿,是的,正则表达式。

于 2010-03-01T23:10:47.847 回答
3

鉴于您对我的其他答案的回复,这应该适用于您指定的严格格式的案例:

    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')。

如果您不熟悉正则表达式,只是为了进一步解释该正则表达式:

(([^/ ]+)/)?相当于 just ([^/ ]+/)?-- 即“不包括正斜杠或空格的任何内容,后跟一个斜杠”。问号使其可选(因此整个子句可能会丢失),最终版本中的额外括号用于创建一个较小的内部组,不带斜线,以供以后提取。

([^ ]+)是“捕获任何不是空格的东西(后面跟一个空格)”——这是门牌号。

([^,]+),是“捕获任何不是逗号的东西(后面是逗号和空格)”——这是街道名称。只要不是逗号,街道名称中的任何内容都是有效的。

([^,]+),再次是相同的,在这种情况下捕获郊区。

([^ ]+)捕获下一个非空格字符串(状态缩写)并跳过其后的空格。

(\\d+)通过捕获任意数量的数字(邮政编码)四舍五入

希望这会有所帮助。

于 2010-03-02T11:04:25.063 回答
2

嗯,可能相当困难,因为格式没有很好地定义。

正则表达式肯定会作为一种快速而肮脏的解决方案。问题是在特殊情况下它可能会失败(产生不正确的结果)。

最好的办法可能是破解一个小的正则表达式,然后在一个真实的数据集(理想情况下你在生产中拥有的所有东西)上运行它,并检查它是否给出了好的结果。可能是很多手工工作,但可能是你能做的最好的......

编辑:顺便说一句,要在 Java 中使用正则表达式,请使用 package 中的方法java.util.regex。只是想我会提到它...

于 2010-03-01T12:10:46.630 回答
2

如果有人感兴趣,我编写了以下正则表达式来解析澳大利亚地址。

r"(?i)(\b(PO BOX|post box)[,\s|.\s|,.|\s]*)?(\b(\d+))(\b(?:(?!\s{2,}).){1,60})\b(New South Wales|Victoria|Queensland|Western Australia|South Australia|Tasmania|VIC|NSW|ACT|QLD|NT|SA|TAS|WA).?[,\s|.\s|,.|\s]*(\b\d{4}).?[,\s|.\s|,.|\s]*(\b(Australia|Au))?")

而这个用于解析 Nex Zealand 地址。

r"(?i)(\b(PO BOX|post box)[,\s|.\s|,.|\s]*)?(\b(\d+))(\b(?:(?!\s{2,}).){1,60})\b(Northland|Auckland|Waikato|Bay of Plenty|Gisborne|Hawke's Bay|Taranaki|Manawatu-Whanganui|Wellington|Tasman|Nelson|Marlborough|West Coast|Canterbury|Otago|Southland).?[,\s|.\s|,.|\s]*(\b\d{4}).?[,\s|.\s|,.|\s]*(\b(New zealand|Newzealand|Nz))?")
于 2020-05-16T09:49:59.360 回答
1

我创建了一个正则表达式,它提取地址组件(例如单元号、街道号码、街道名称,包括郊区、州和邮政编码)这适用于澳大利亚地址,但它可以轻松地为其他地址定制,唯一需要更新的就是其他地址地址是状态部分。 https://regex101.com/library/5bj4wi

于 2017-05-08T05:40:46.140 回答
0

您可以使用String.split,首先使用,,然后使用.or /

于 2010-03-01T12:09:44.993 回答
0

对于商业解决方案,您可以尝试 address-parser.com 。

于 2010-06-09T08:58:46.477 回答