Java:解析澳大利亚街道地址

时间:2010-03-01 12:06:05

标签: java string parsing street-address

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

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

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


请参阅:Parse A Steet Address into components

必须是Java,不能发出http请求(例如发给Web API)。


编辑:假设始终遵循指定的格式。我没有问题,向用户发送错误格式化的字符串,并告诉他们遵循格式(我在上面已经描述过)。

6 个答案:

答案 0 :(得分:9)

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

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

地址更糟糕。当然,大多数人会将7/21 Smith St用于单位,或29-33 Jones St用于跨越多个街道号码的位置,但人们不一致。 1-5 Brown St单位1是5号,还是位于该街道#1到#5的位置? 7A是一个单独的细分街道地址,还是#7的单元A?

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

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

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

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

答案 1 :(得分: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')。

如果您不熟悉正则表达式,只需要进一步解释正则表达式:

(([^/ ]+)/)?相当于只有([^/ ]+/)? - 也就是说,'任何不包括正斜杠或空格,后跟斜线'。问号使它成为可选的(因此整个子句可能会丢失),最终版本中的额外括号是创建一个较小的内部组,没有斜杠,以便以后提取。

([^ ]+)是'捕获任何不是空格的东西(后跟空格)' - 这是街道号码。

([^,]+),'捕获任何不是逗号的内容(后面跟逗号和空格)' - 这是街道名称。街道名称中的任何内容都有效,只要它不是逗号。

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

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

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

来完成

希望这有帮助。

答案 2 :(得分:1)

嗯,可能很难,因为格式没有明确定义。

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

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

编辑: BTW,要在Java中使用正则表达式,请使用包java.util.regex中的方法。我以为我会提到它......

答案 3 :(得分:1)

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

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))?")

这个用于解析Nexland地址的地址。

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))?")

答案 4 :(得分:0)

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

答案 5 :(得分:0)

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