如何通过前缀正确匹配英国邮政编码?

时间:2014-02-06 23:13:00

标签: match postal-code

我有很多餐馆都在伦敦的某些邮政编码区域提供服务,例如:

  • EC1
  • WC1
  • WC2
  • W1

当有人搜索送到家中的餐馆时,他们会输入完整的邮政编码。

有些人使用空格正确输入邮政编码,其中一些只输入附加的所有字母和数字,没有空格分隔符。为了协调事物,我在尝试匹配之前删除了邮政编码中的任何空格。

到目前为止,我曾经将邮政编码与前缀匹配,只是检查它是否以相关前缀开头,但后来我意识到这不是万无一失的:

  • WC1E123 =>正确匹配WC1
  • W1ABC =>正确匹配W1
  • W10ABC => W1的错误匹配应仅与W10前缀
  • 匹配

我如何知道,给出一个没有空格的完整邮政编码,如果匹配给定的前缀,同时不会使W1 / {{1以上测试?

这个问题是否有任何解决方案,不会强迫客户输入邮政编码,空格位置正确?

6 个答案:

答案 0 :(得分:16)

英国有6种可能的邮政编码格式:

  • A9 9AA
  • A9A 9AA
  • A99 9AA
  • AA9 9AA
  • AA9A 9AA
  • AA99 9AA

我认为您的解决方案需要有两个部分。第一是验证输入;第二个是抓住第一部分。

<强>验证

这非常重要,尽管我已经意识到你已经说过这不是你想要做的事情,但是如果没有它,你将很难获得正确的前缀,并可能将你的司机送到错误的地方!

有两种方法可以做到这一点,要么使用第三方来帮助您捕获完整的&amp;正确的地址(许多可用,包括http://www.qas.co.uk/knowledge-centre/product-information/address-postcode-finder.htm(我的公司)),或至少使用一些注册/类似的健全性测试来验证邮政编码 - 例如Dmitri给你的链接。

如果你查看你列出的测试用例 - W1ABC和W10ABC是无效的邮政编码 - 如果我们得到那个位正确,那么下一位变得容易多了。

提取前缀

假设您现在拥有一个完整有效的邮政编码,只需要第一部分(outcode)变得更容易 - 有或没有空格。因为下半部分(incode)有一个标准格式 9AA ,数字-α-alpha,我会通过发现并删除它来做,只留下你的outcode是否是W1来自W1 0AA ,或来自W10 0AA的W10。

或者,如果您使用第三方捕获地址 - 他们中的大多数将能够为您单独返回incode和outcode。

答案 1 :(得分:2)

下图说明了英国邮政编码的格式:

Format of UK postcodes

来源:https://www.getthedata.com/postcode(我的网站)所以你可以看到你需要 Outcode 给出你的要求(给出一个没有空格的完整邮政编码)只是你的无空间邮政编码减去最后三个字符。

在PHP中,这将是:

$outcode = substr($postcode_no_space, 0, -3)

当然这对验证邮政编码无效,但正如您在评论中指出的那样,问题与验证无关。

答案 2 :(得分:1)

我使用以下仅与前缀部分匹配的正则表达式,但使用前瞻以确保完整的邮政编码有效(包括可选空格)

(GIR|[A-PR-UWYZ]([0-9]{1,2}|([A-HK-Y][0-9]|[A-HK-Y][0-9]([0-9]|[ABEHMNPRV-Y]))|[0-9][A-HJKS-UW]))(?=( )?[0-9][ABD-HJLNP-UW-Z]{2})

它不是很完美,因为它会匹配一些无效的邮政编码(例如,启动AA等),但是如果你用它来查找前缀,那么它应该可以解决问题。

PS。我刚才注意到英国政府提供的正则表达式自我第一次实施以来已经更新。 在哪种情况下,这可以更新为:

(GIR|([A-Z-[QVX][0-9][0-9]?)|(([A-Z-[QVX][A-Z-[IJZ][0-9][0-9]?)|(([A-Z-[QVX][0-9][A-HJKSTUW])|([A-Z-[QVX][A-Z-[IJZ][0-9][ABEHMNPRVWXY]))))(?=( )?[0-9][A-Z-[CIKMOV]{2})

答案 3 :(得分:1)

在php中我做

$first=trim(substr(trim($postcode),0,-3));

获取邮政编码的第一部分。我已经使用它多年,只是工作。用户是否在中间包含空格(或2个空格)并不重要,因为最后一部分总是3个字符。我在一家分销公司工作,我们会为某些邮政编码区域收取更多费用。如果他们错过了最后一个角色,那么有人会错误地输入邮政编码。

如果上述情况不够好。

您可以验证用户提供给您的邮政编码是否有效,然后http://postcodes.io/可以提供帮助。

http://api.postcodes.io/postcodes/W11%202AQ会根据邮政编码是否有效为您提供一些JSON。

{
    "status": 200,
    "result": {
        "postcode": "W11 2AQ",
        "quality": 1,
        "eastings": 524990,
        "northings": 181250,
        "country": "England",
        "nhs_ha": "London",
        "longitude": -0.200056238526337,
        "latitude": 51.5163540527233,
        "parliamentary_constituency": "Kensington",
        "european_electoral_region": "London",
        "primary_care_trust": "Kensington and Chelsea",
        "region": "London",
        "lsoa": "Kensington and Chelsea 004A",
        "msoa": "Kensington and Chelsea 004",
        "nuts": "Colville",
        "incode": "2AQ",
        "outcode": "W11",
        "admin_district": "Kensington and Chelsea",
        "parish": "Kensington and Chelsea, unparished area",
        "admin_county": null,
        "admin_ward": "Colville",
        "ccg": "NHS West London (Kensington and Chelsea, Queenís Park and Paddington)",
        "codes": {
            "admin_district": "E09000020",
            "admin_county": "E99999999",
            "admin_ward": "E05009392",
            "parish": "E43000210",
            "ccg": "E38000202"
        }
    }
}

JSON的一部分是"outcode": "W11",我认为这正是您所寻找的。

您还可以使用“eastings”:524990,“northings”:181250,字段来计算从餐厅到用户的直线距离。单位是米。使用毕达哥拉斯。

答案 4 :(得分:0)

由于您可以计算客户输入的邮政编码的长度,并且邮政编码的格式最后总是有9AA,您可以将代码分解为几个案例并通过执行以下操作返回匹配

firstPart -> postcode with last 3 characters removed
firstPartLength -> length of firstPart
switch (firstPartLength){
    case 2:
        code to compare prefix against A99AA format
    case 3:
        code to compare prefix against A9A9AA, A999AA, AA99AA format
    case 4:
        code to compare prefix against AA999AA format

或者如果您不想截断最后3个字符,

length -> length of postcode
switch (length){
    case 5:
        code to compare prefix against A99AA format
    case 6:
        code to compare prefix against A9A9AA, A999AA, AA99AA format
    case 7:
        code to compare prefix against AA999AA format

答案 5 :(得分:0)

假设每个邮政编码都以 9AA 结尾,并且每个输入邮政编码都有效,则可以使用以下正则表达式来匹配区域前缀:

^(\w{2,4})\s*[0-9][a-zA-Z]{2}$

第一个捕获组返回所需的前缀。