寻找一种快速而肮脏的方式将澳大利亚街道地址解析为其部分:
3A/45 Jindabyne Rd, Oakleigh, VIC 3166
应分为:
"3A"
,45
,"Jindabyne Rd"
"Oakleigh"
,"VIC"
,3166
郊区名称可以包含多个单词,街道名称也可以。
请参阅:Parse A Steet Address into components
必须是Java,不能发出http请求(例如发给Web API)。
编辑:假设始终遵循指定的格式。我没有问题,向用户发送错误格式化的字符串,并告诉他们遵循格式(我在上面已经描述过)。
答案 0 :(得分:9)
老实说,你在这里为自己设定了一个相当Sisyphean的挑战,我不确定它是否值得。除非您的数据来自已知来源,并且具有非常明确的格式,否则您将获得完全无用的数据。如果您正在处理自由文本,那么人们会以您不相信的方式搞砸他们的地址。
您真的想(自己)尝试解析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
是一个单独的细分街道地址,还是#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。